def testAlwaysSeriliaze(self): message = json_format_proto3_pb2.TestMessage(string_value='foo') self.assertEqual( json.loads(json_format.MessageToJson(message, True)), json.loads('{' '"repeatedStringValue": [],' '"stringValue": "foo",' '"repeatedBoolValue": [],' '"repeatedUint32Value": [],' '"repeatedInt32Value": [],' '"enumValue": "FOO",' '"int32Value": 0,' '"floatValue": 0,' '"int64Value": "0",' '"uint32Value": 0,' '"repeatedBytesValue": [],' '"repeatedUint64Value": [],' '"repeatedDoubleValue": [],' '"bytesValue": "",' '"boolValue": false,' '"repeatedEnumValue": [],' '"uint64Value": "0",' '"doubleValue": 0,' '"repeatedFloatValue": [],' '"repeatedInt64Value": [],' '"repeatedMessageValue": []}')) parsed_message = json_format_proto3_pb2.TestMessage() self.CheckParseBack(message, parsed_message)
def testAllFieldsToJson(self): message = json_format_proto3_pb2.TestMessage() text = ( '{"int32Value": 20, ' '"int64Value": "-20", ' '"uint32Value": 3120987654,' '"uint64Value": "12345678900",' '"floatValue": "-Infinity",' '"doubleValue": 3.1415,' '"boolValue": true,' '"stringValue": "foo",' '"bytesValue": "YmFy",' '"messageValue": {"value": 10},' '"enumValue": "BAR",' '"repeatedInt32Value": [2147483647, -2147483648],' '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],' '"repeatedUint32Value": [268435455, 134217727],' '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],' '"repeatedFloatValue": [0],' '"repeatedDoubleValue": [1e-15, "Infinity"],' '"repeatedBoolValue": [true, false],' '"repeatedStringValue": ["Few symbols!#$,;", "bar"],' '"repeatedBytesValue": ["Zm9v", "YmFy"],' '"repeatedMessageValue": [{"value": 10}, {"value": 11}],' '"repeatedEnumValue": ["FOO", "BAR"]' '}') self.FillAllFields(message) self.assertEqual(json.loads(json_format.MessageToJson(message)), json.loads(text)) parsed_message = json_format_proto3_pb2.TestMessage() json_format.Parse(text, parsed_message) self.assertEqual(message, parsed_message)
def testUnknownEnumToJsonAndBack(self): text = '{\n "enumValue": 999\n}' message = json_format_proto3_pb2.TestMessage() message.enum_value = 999 self.assertEqual(json_format.MessageToJson(message), text) parsed_message = json_format_proto3_pb2.TestMessage() json_format.Parse(text, parsed_message) self.assertEqual(message, parsed_message)
def testNanFloat(self): message = json_format_proto3_pb2.TestMessage() message.float_value = float('nan') text = '{\n "floatValue": "NaN"\n}' self.assertEqual(json_format.MessageToJson(message), text) parsed_message = json_format_proto3_pb2.TestMessage() json_format.Parse(text, parsed_message) self.assertTrue(math.isnan(parsed_message.float_value))
def testPartialMessageToJson(self): message = json_format_proto3_pb2.TestMessage( string_value='test', repeated_int32_value=[89, 4]) self.assertEqual( json.loads(json_format.MessageToJson(message)), json.loads('{"stringValue": "test", ' '"repeatedInt32Value": [89, 4]}')) parsed_message = json_format_proto3_pb2.TestMessage() self.CheckParseBack(message, parsed_message)
def testJsonEscapeString(self): message = json_format_proto3_pb2.TestMessage() if sys.version_info[0] < 3: message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9' else: message.string_value = '&\n<\"\r>\b\t\f\\\001/' message.string_value += ( b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8') self.assertEqual( json_format.MessageToJson(message), '{\n "stringValue": ' '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}') parsed_message = json_format_proto3_pb2.TestMessage() self.CheckParseBack(message, parsed_message) text = '{"int32Value": "\u0031"}' json_format.Parse(text, message) self.assertEqual(message.int32_value, 1)
def testIntegersRepresentedAsFloat(self): message = json_format_proto3_pb2.TestMessage() json_format.Parse('{"int32Value": -2.147483648e9}', message) self.assertEqual(message.int32_value, -2147483648) json_format.Parse('{"int32Value": 1e5}', message) self.assertEqual(message.int32_value, 100000) json_format.Parse('{"int32Value": 1.0}', message) self.assertEqual(message.int32_value, 1)
def testParseNull(self): message = json_format_proto3_pb2.TestMessage() parsed_message = json_format_proto3_pb2.TestMessage() self.FillAllFields(parsed_message) json_format.Parse( '{"int32Value": null, ' '"int64Value": null, ' '"uint32Value": null,' '"uint64Value": null,' '"floatValue": null,' '"doubleValue": null,' '"boolValue": null,' '"stringValue": null,' '"bytesValue": null,' '"messageValue": null,' '"enumValue": null,' '"repeatedInt32Value": null,' '"repeatedInt64Value": null,' '"repeatedUint32Value": null,' '"repeatedUint64Value": null,' '"repeatedFloatValue": null,' '"repeatedDoubleValue": null,' '"repeatedBoolValue": null,' '"repeatedStringValue": null,' '"repeatedBytesValue": null,' '"repeatedMessageValue": null,' '"repeatedEnumValue": null' '}', parsed_message) self.assertEqual(message, parsed_message) # Null and {} should have different behavior for sub message. self.assertFalse(parsed_message.HasField('message_value')) json_format.Parse('{"messageValue": {}}', parsed_message) self.assertTrue(parsed_message.HasField('message_value')) # Null is not allowed to be used as an element in repeated field. self.assertRaisesRegex( json_format.ParseError, 'Failed to parse repeatedInt32Value field: ' 'null is not allowed to be used as an element in a repeated field.', json_format.Parse, '{"repeatedInt32Value":[1, null]}', parsed_message) self.CheckError( '{"repeatedMessageValue":[null]}', 'Failed to parse repeatedMessageValue field: null is not' ' allowed to be used as an element in a repeated field.')
def testPreservingProtoFieldNames(self): message = json_format_proto3_pb2.TestMessage() message.int32_value = 12345 self.assertEqual('{\n "int32Value": 12345\n}', json_format.MessageToJson(message)) self.assertEqual('{\n "int32_value": 12345\n}', json_format.MessageToJson(message, False, True)) # When including_default_value_fields is True. message = json_format_proto3_pb2.TestTimestamp() self.assertEqual('{\n "repeatedValue": []\n}', json_format.MessageToJson(message, True, False)) self.assertEqual('{\n "repeated_value": []\n}', json_format.MessageToJson(message, True, True)) # Parsers accept both original proto field names and lowerCamelCase names. message = json_format_proto3_pb2.TestMessage() json_format.Parse('{"int32Value": 54321}', message) self.assertEqual(54321, message.int32_value) json_format.Parse('{"int32_value": 12345}', message) self.assertEqual(12345, message.int32_value)
def testIgnoreUnknownField(self): text = '{"unknownName": 1}' parsed_message = json_format_proto3_pb2.TestMessage() json_format.Parse(text, parsed_message, ignore_unknown_fields=True) text = ('{\n' ' "repeatedValue": [ {\n' ' "@type": "type.googleapis.com/proto3.MessageType",\n' ' "unknownName": 1\n' ' }]\n' '}\n') parsed_message = json_format_proto3_pb2.TestAny() json_format.Parse(text, parsed_message, ignore_unknown_fields=True)
def testFormatEnumsAsInts(self): message = json_format_proto3_pb2.TestMessage() message.enum_value = json_format_proto3_pb2.BAR message.repeated_enum_value.append(json_format_proto3_pb2.FOO) message.repeated_enum_value.append(json_format_proto3_pb2.BAR) self.assertEqual( json.loads('{\n' ' "enumValue": 1,\n' ' "repeatedEnumValue": [0, 1]\n' '}\n'), json.loads( json_format.MessageToJson(message, use_integers_for_enums=True)))
def testSurrogates(self): # Test correct surrogate handling. message = json_format_proto3_pb2.TestMessage() json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message) self.assertEqual(message.string_value, b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict')) # Error case: unpaired high surrogate. self.CheckError('{"stringValue": "\\uD83D"}', r'Invalid \\uXXXX escape|Unpaired.*surrogate') # Unpaired low surrogate. self.CheckError('{"stringValue": "\\uDE01"}', r'Invalid \\uXXXX escape|Unpaired.*surrogate')
def testAnyMessage(self): message = json_format_proto3_pb2.TestAny() value1 = json_format_proto3_pb2.MessageType() value2 = json_format_proto3_pb2.MessageType() value1.value = 1234 value2.value = 5678 message.value.Pack(value1) message.repeated_value.add().Pack(value1) message.repeated_value.add().Pack(value2) message.repeated_value.add() self.assertEqual( json.loads(json_format.MessageToJson(message, True)), json.loads( '{\n' ' "repeatedValue": [ {\n' ' "@type": "type.googleapis.com/proto3.MessageType",\n' ' "value": 1234\n' ' }, {\n' ' "@type": "type.googleapis.com/proto3.MessageType",\n' ' "value": 5678\n' ' },\n' ' {}],\n' ' "value": {\n' ' "@type": "type.googleapis.com/proto3.MessageType",\n' ' "value": 1234\n' ' }\n' '}\n')) parsed_message = json_format_proto3_pb2.TestAny() self.CheckParseBack(message, parsed_message) # Must print @type first test_message = json_format_proto3_pb2.TestMessage(bool_value=True, int32_value=20, int64_value=-20, uint32_value=20, uint64_value=20, double_value=3.14, string_value='foo') message.Clear() message.value.Pack(test_message) self.assertEqual( json_format.MessageToJson(message, False)[0:68], '{\n' ' "value": {\n' ' "@type": "type.googleapis.com/proto3.TestMessage"')
def testParseEnumValue(self): message = json_format_proto3_pb2.TestMessage() text = '{"enumValue": 0}' json_format.Parse(text, message) text = '{"enumValue": 1}' json_format.Parse(text, message) self.CheckError( '{"enumValue": "baz"}', 'Failed to parse enumValue field: Invalid enum value baz ' 'for enum type proto3.EnumType.') # Proto3 accepts numeric unknown enums. text = '{"enumValue": 12345}' json_format.Parse(text, message) # Proto2 does not accept unknown enums. message = unittest_pb2.TestAllTypes() self.assertRaisesRegex( json_format.ParseError, 'Failed to parse optionalNestedEnum field: Invalid enum value 12345 ' 'for enum type protobuf_unittest.TestAllTypes.NestedEnum.', json_format.Parse, '{"optionalNestedEnum": 12345}', message)
def testSortKeys(self): # Testing sort_keys is not perfectly working, as by random luck we could # get the output sorted. We just use a selection of names. message = json_format_proto3_pb2.TestMessage(bool_value=True, int32_value=1, int64_value=3, uint32_value=4, string_value='bla') self.assertEqual( json_format.MessageToJson(message, sort_keys=True), # We use json.dumps() instead of a hardcoded string due to differences # between Python 2 and Python 3. json.dumps( { 'boolValue': True, 'int32Value': 1, 'int64Value': '3', 'uint32Value': 4, 'stringValue': 'bla' }, indent=2, sort_keys=True))
def testInvalidIntegerValue(self): message = json_format_proto3_pb2.TestMessage() text = '{"int32Value": 0x12345}' self.assertRaises(json_format.ParseError, json_format.Parse, text, message) self.CheckError( '{"int32Value": 1.5}', 'Failed to parse int32Value field: ' 'Couldn\'t parse integer: 1.5.') self.CheckError('{"int32Value": 012345}', (r'Failed to load JSON: Expecting \'?,\'? delimiter: ' r'line 1.')) self.CheckError( '{"int32Value": " 1 "}', 'Failed to parse int32Value field: ' 'Couldn\'t parse integer: " 1 ".') self.CheckError( '{"int32Value": "1 "}', 'Failed to parse int32Value field: ' 'Couldn\'t parse integer: "1 ".') self.CheckError( '{"int32Value": 12345678901234567890}', 'Failed to parse int32Value field: Value out of range: ' '12345678901234567890.') self.CheckError( '{"uint32Value": -1}', 'Failed to parse uint32Value field: ' 'Value out of range: -1.')
def testMessageToDict(self): message = json_format_proto3_pb2.TestMessage() message.int32_value = 12345 expected = {'int32Value': 12345} self.assertEqual(expected, json_format.MessageToDict(message))
def testParseDict(self): expected = 12345 js_dict = {'int32Value': expected} message = json_format_proto3_pb2.TestMessage() json_format.ParseDict(js_dict, message) self.assertEqual(expected, message.int32_value)
def testIndent(self): message = json_format_proto3_pb2.TestMessage() message.int32_value = 12345 self.assertEqual('{\n"int32Value": 12345\n}', json_format.MessageToJson(message, indent=0))
def CheckError(self, text, error_message): message = json_format_proto3_pb2.TestMessage() self.assertRaisesRegex(json_format.ParseError, error_message, json_format.Parse, text, message)
def testEmptyMessageToJson(self): message = json_format_proto3_pb2.TestMessage() self.assertEqual(json_format.MessageToJson(message), '{}') parsed_message = json_format_proto3_pb2.TestMessage() self.CheckParseBack(message, parsed_message)