Commit 9e69594a authored by Leon Barrett's avatar Leon Barrett Committed by Jie Luo

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
parent 8d6f8df1
...@@ -495,6 +495,8 @@ class JsonFormatTest(JsonFormatBase): ...@@ -495,6 +495,8 @@ class JsonFormatTest(JsonFormatBase):
message.value['email'] = None message.value['email'] = None
message.value.get_or_create_struct('address')['city'] = 'SFO' message.value.get_or_create_struct('address')['city'] = 'SFO'
message.value['address']['house_number'] = 1024 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 = message.value.get_or_create_list('list')
struct_list.extend([6, 'seven', True, False, None]) struct_list.extend([6, 'seven', True, False, None])
struct_list.add_struct()['subkey2'] = 9 struct_list.add_struct()['subkey2'] = 9
...@@ -509,6 +511,8 @@ class JsonFormatTest(JsonFormatBase): ...@@ -509,6 +511,8 @@ class JsonFormatTest(JsonFormatBase):
' "city": "SFO", ' ' "city": "SFO", '
' "house_number": 1024' ' "house_number": 1024'
' }, ' ' }, '
' "empty_struct": {}, '
' "empty_list": [], '
' "age": 10, ' ' "age": 10, '
' "name": "Jim", ' ' "name": "Jim", '
' "attend": true, ' ' "attend": true, '
...@@ -519,6 +523,8 @@ class JsonFormatTest(JsonFormatBase): ...@@ -519,6 +523,8 @@ class JsonFormatTest(JsonFormatBase):
'}')) '}'))
parsed_message = json_format_proto3_pb2.TestStruct() parsed_message = json_format_proto3_pb2.TestStruct()
self.CheckParseBack(message, parsed_message) 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): def testValueMessage(self):
message = json_format_proto3_pb2.TestValue() message = json_format_proto3_pb2.TestValue()
......
...@@ -614,6 +614,9 @@ class _Parser(object): ...@@ -614,6 +614,9 @@ class _Parser(object):
if not isinstance(value, dict): if not isinstance(value, dict):
raise ParseError( raise ParseError(
'Struct must be in a dict which is {0}.'.format(value)) '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: for key in value:
self._ConvertValueMessage(value[key], message.fields[key]) self._ConvertValueMessage(value[key], message.fields[key])
return return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment