diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py index f323d0e23a261..17258bc5d74b8 100644 --- a/python/google/protobuf/internal/json_format_test.py +++ b/python/google/protobuf/internal/json_format_test.py @@ -1601,6 +1601,28 @@ def testParseDictAnyDescriptorPoolMissingType(self): 'TestAny.any_value.', ) + def testParseDictNestedAnyDescriptorPoolMissingType(self): + # Confirm that ParseDict nondestructive with empty pool + js_dict = { + '@type': 'type.googleapis.com/google.protobuf.Any', + 'value': { + '@type': 'type.googleapis.com/protobuf_unittest.TestAny', + 'any_value': { + '@type': 'type.googleapis.com/UnknownMessageType', + }, + }, + } + js_dict_copy = json.loads(json.dumps(js_dict)) + with self.assertRaises(json_format.ParseError) as cm: + json_format.ParseDict(js_dict_copy, any_pb2.Any()) + self.assertEqual( + str(cm.exception), + 'Failed to parse any_value field: Can not find message descriptor by' + ' type_url: type.googleapis.com/UnknownMessageType at' + ' Any.value.any_value.', + ) + self.assertEqual(js_dict, js_dict_copy) + def testParseDictUnknownValueType(self): class UnknownClass(object): diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 7891be94ba525..3eafd132159ec 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -734,8 +734,10 @@ def _ConvertAnyMessage(self, value, message, path): )(self) else: del value['@type'] - self._ConvertFieldValuePair(value, sub_message, path) - value['@type'] = type_url + try: + self._ConvertFieldValuePair(value, sub_message, path) + finally: + value['@type'] = type_url # Sets Any message message.value = sub_message.SerializeToString() message.type_url = type_url