瀏覽代碼

Fix parsing empty Struct Values from Json (#5211)

* Fix parsing empty Struct Values from Json

This fixes a bug. When parsing a struct from JSON like
    struct = json_format.Parse('{"k": {}}', Struct())
then the struct's "k" value would end up not initialized, and accessing
the value would raise an error.
    In[1]: struct['k']
    ValueError: Value not set
That seems to be because the Struct field of the Value was not set.
    In[2]: struct
    Out[2]:
    fields {
      key: "k"
      value {
      }
    }

This commit makes sure that the Value's Struct field is initialized even
if the Struct has no values itself.

This commit also extends a test to cover this case.

* Additionally test for empty list
Leon Barrett 7 年之前
父節點
當前提交
9e69594adf
共有 2 個文件被更改,包括 9 次插入0 次删除
  1. 6 0
      python/google/protobuf/internal/json_format_test.py
  2. 3 0
      python/google/protobuf/json_format.py

+ 6 - 0
python/google/protobuf/internal/json_format_test.py

@@ -495,6 +495,8 @@ class JsonFormatTest(JsonFormatBase):
     message.value['email'] = None
     message.value.get_or_create_struct('address')['city'] = 'SFO'
     message.value['address']['house_number'] = 1024
+    message.value.get_or_create_struct('empty_struct')
+    message.value.get_or_create_list('empty_list')
     struct_list = message.value.get_or_create_list('list')
     struct_list.extend([6, 'seven', True, False, None])
     struct_list.add_struct()['subkey2'] = 9
@@ -509,6 +511,8 @@ class JsonFormatTest(JsonFormatBase):
             '      "city": "SFO", '
             '      "house_number": 1024'
             '    }, '
+            '    "empty_struct": {}, '
+            '    "empty_list": [], '
             '    "age": 10, '
             '    "name": "Jim", '
             '    "attend": true, '
@@ -519,6 +523,8 @@ class JsonFormatTest(JsonFormatBase):
             '}'))
     parsed_message = json_format_proto3_pb2.TestStruct()
     self.CheckParseBack(message, parsed_message)
+    parsed_message.value['empty_struct']  # check for regression; this used to raise
+    parsed_message.value['empty_list']
 
   def testValueMessage(self):
     message = json_format_proto3_pb2.TestValue()

+ 3 - 0
python/google/protobuf/json_format.py

@@ -614,6 +614,9 @@ class _Parser(object):
     if not isinstance(value, dict):
       raise ParseError(
           'Struct must be in a dict which is {0}.'.format(value))
+    # Clear will mark the struct as modified so it will be created even if
+    # there are no values.
+    message.Clear()
     for key in value:
       self._ConvertValueMessage(value[key], message.fields[key])
     return