Imported Upstream version 3.8.0
[platform/upstream/protobuf.git] / python / google / protobuf / internal / json_format_test.py
1 #! /usr/bin/env python
2 #
3 # Protocol Buffers - Google's data interchange format
4 # Copyright 2008 Google Inc.  All rights reserved.
5 # https://developers.google.com/protocol-buffers/
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are
9 # met:
10 #
11 #     * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 #     * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following disclaimer
15 # in the documentation and/or other materials provided with the
16 # distribution.
17 #     * Neither the name of Google Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 """Test for google.protobuf.json_format."""
34
35 __author__ = 'jieluo@google.com (Jie Luo)'
36
37 import json
38 import math
39 import sys
40
41 try:
42   import unittest2 as unittest  #PY26
43 except ImportError:
44   import unittest
45
46 from google.protobuf import any_pb2
47 from google.protobuf import duration_pb2
48 from google.protobuf import field_mask_pb2
49 from google.protobuf import struct_pb2
50 from google.protobuf import timestamp_pb2
51 from google.protobuf import wrappers_pb2
52 from google.protobuf import any_test_pb2
53 from google.protobuf import unittest_mset_pb2
54 from google.protobuf import unittest_pb2
55 from google.protobuf import descriptor_pool
56 from google.protobuf import json_format
57 from google.protobuf.util import json_format_proto3_pb2
58
59
60 class JsonFormatBase(unittest.TestCase):
61
62   def FillAllFields(self, message):
63     message.int32_value = 20
64     message.int64_value = -20
65     message.uint32_value = 3120987654
66     message.uint64_value = 12345678900
67     message.float_value = float('-inf')
68     message.double_value = 3.1415
69     message.bool_value = True
70     message.string_value = 'foo'
71     message.bytes_value = b'bar'
72     message.message_value.value = 10
73     message.enum_value = json_format_proto3_pb2.BAR
74     # Repeated
75     message.repeated_int32_value.append(0x7FFFFFFF)
76     message.repeated_int32_value.append(-2147483648)
77     message.repeated_int64_value.append(9007199254740992)
78     message.repeated_int64_value.append(-9007199254740992)
79     message.repeated_uint32_value.append(0xFFFFFFF)
80     message.repeated_uint32_value.append(0x7FFFFFF)
81     message.repeated_uint64_value.append(9007199254740992)
82     message.repeated_uint64_value.append(9007199254740991)
83     message.repeated_float_value.append(0)
84
85     message.repeated_double_value.append(1E-15)
86     message.repeated_double_value.append(float('inf'))
87     message.repeated_bool_value.append(True)
88     message.repeated_bool_value.append(False)
89     message.repeated_string_value.append('Few symbols!#$,;')
90     message.repeated_string_value.append('bar')
91     message.repeated_bytes_value.append(b'foo')
92     message.repeated_bytes_value.append(b'bar')
93     message.repeated_message_value.add().value = 10
94     message.repeated_message_value.add().value = 11
95     message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
96     message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
97     self.message = message
98
99   def CheckParseBack(self, message, parsed_message):
100     json_format.Parse(json_format.MessageToJson(message),
101                       parsed_message)
102     self.assertEqual(message, parsed_message)
103
104   def CheckError(self, text, error_message):
105     message = json_format_proto3_pb2.TestMessage()
106     self.assertRaisesRegexp(
107         json_format.ParseError,
108         error_message,
109         json_format.Parse, text, message)
110
111
112 class JsonFormatTest(JsonFormatBase):
113
114   def testEmptyMessageToJson(self):
115     message = json_format_proto3_pb2.TestMessage()
116     self.assertEqual(json_format.MessageToJson(message),
117                      '{}')
118     parsed_message = json_format_proto3_pb2.TestMessage()
119     self.CheckParseBack(message, parsed_message)
120
121   def testPartialMessageToJson(self):
122     message = json_format_proto3_pb2.TestMessage(
123         string_value='test',
124         repeated_int32_value=[89, 4])
125     self.assertEqual(json.loads(json_format.MessageToJson(message)),
126                      json.loads('{"stringValue": "test", '
127                                 '"repeatedInt32Value": [89, 4]}'))
128     parsed_message = json_format_proto3_pb2.TestMessage()
129     self.CheckParseBack(message, parsed_message)
130
131   def testAllFieldsToJson(self):
132     message = json_format_proto3_pb2.TestMessage()
133     text = ('{"int32Value": 20, '
134             '"int64Value": "-20", '
135             '"uint32Value": 3120987654,'
136             '"uint64Value": "12345678900",'
137             '"floatValue": "-Infinity",'
138             '"doubleValue": 3.1415,'
139             '"boolValue": true,'
140             '"stringValue": "foo",'
141             '"bytesValue": "YmFy",'
142             '"messageValue": {"value": 10},'
143             '"enumValue": "BAR",'
144             '"repeatedInt32Value": [2147483647, -2147483648],'
145             '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],'
146             '"repeatedUint32Value": [268435455, 134217727],'
147             '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],'
148             '"repeatedFloatValue": [0],'
149             '"repeatedDoubleValue": [1e-15, "Infinity"],'
150             '"repeatedBoolValue": [true, false],'
151             '"repeatedStringValue": ["Few symbols!#$,;", "bar"],'
152             '"repeatedBytesValue": ["Zm9v", "YmFy"],'
153             '"repeatedMessageValue": [{"value": 10}, {"value": 11}],'
154             '"repeatedEnumValue": ["FOO", "BAR"]'
155             '}')
156     self.FillAllFields(message)
157     self.assertEqual(
158         json.loads(json_format.MessageToJson(message)),
159         json.loads(text))
160     parsed_message = json_format_proto3_pb2.TestMessage()
161     json_format.Parse(text, parsed_message)
162     self.assertEqual(message, parsed_message)
163
164   def testUnknownEnumToJsonAndBack(self):
165     text = '{\n  "enumValue": 999\n}'
166     message = json_format_proto3_pb2.TestMessage()
167     message.enum_value = 999
168     self.assertEqual(json_format.MessageToJson(message),
169                      text)
170     parsed_message = json_format_proto3_pb2.TestMessage()
171     json_format.Parse(text, parsed_message)
172     self.assertEqual(message, parsed_message)
173
174   def testExtensionToJsonAndBack(self):
175     message = unittest_mset_pb2.TestMessageSetContainer()
176     ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
177     ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
178     message.message_set.Extensions[ext1].i = 23
179     message.message_set.Extensions[ext2].str = 'foo'
180     message_text = json_format.MessageToJson(
181         message
182     )
183     parsed_message = unittest_mset_pb2.TestMessageSetContainer()
184     json_format.Parse(message_text, parsed_message)
185     self.assertEqual(message, parsed_message)
186
187   def testExtensionErrors(self):
188     self.CheckError('{"[extensionField]": {}}',
189                     'Message type proto3.TestMessage does not have extensions')
190
191   def testExtensionToDictAndBack(self):
192     message = unittest_mset_pb2.TestMessageSetContainer()
193     ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
194     ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
195     message.message_set.Extensions[ext1].i = 23
196     message.message_set.Extensions[ext2].str = 'foo'
197     message_dict = json_format.MessageToDict(
198         message
199     )
200     parsed_message = unittest_mset_pb2.TestMessageSetContainer()
201     json_format.ParseDict(message_dict, parsed_message)
202     self.assertEqual(message, parsed_message)
203
204   def testExtensionToDictAndBackWithScalar(self):
205     message = unittest_pb2.TestAllExtensions()
206     ext1 = unittest_pb2.TestNestedExtension.test
207     message.Extensions[ext1] = 'data'
208     message_dict = json_format.MessageToDict(
209         message
210     )
211     parsed_message = unittest_pb2.TestAllExtensions()
212     json_format.ParseDict(message_dict, parsed_message)
213     self.assertEqual(message, parsed_message)
214
215   def testJsonParseDictToAnyDoesNotAlterInput(self):
216     orig_dict = {
217         'int32Value': 20,
218         '@type': 'type.googleapis.com/proto3.TestMessage'
219     }
220     copied_dict = json.loads(json.dumps(orig_dict))
221     parsed_message = any_pb2.Any()
222     json_format.ParseDict(copied_dict, parsed_message)
223     self.assertEqual(copied_dict, orig_dict)
224
225   def testExtensionSerializationDictMatchesProto3Spec(self):
226     """See go/proto3-json-spec for spec.
227     """
228     message = unittest_mset_pb2.TestMessageSetContainer()
229     ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
230     ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
231     message.message_set.Extensions[ext1].i = 23
232     message.message_set.Extensions[ext2].str = 'foo'
233     message_dict = json_format.MessageToDict(
234         message
235     )
236     golden_dict = {
237         'messageSet': {
238             '[protobuf_unittest.'
239             'TestMessageSetExtension1.messageSetExtension]': {
240                 'i': 23,
241             },
242             '[protobuf_unittest.'
243             'TestMessageSetExtension2.messageSetExtension]': {
244                 'str': u'foo',
245             },
246         },
247     }
248     self.assertEqual(golden_dict, message_dict)
249
250
251   def testExtensionSerializationJsonMatchesProto3Spec(self):
252     """See go/proto3-json-spec for spec.
253     """
254     message = unittest_mset_pb2.TestMessageSetContainer()
255     ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
256     ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
257     message.message_set.Extensions[ext1].i = 23
258     message.message_set.Extensions[ext2].str = 'foo'
259     message_text = json_format.MessageToJson(
260         message
261     )
262     ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
263                  'messageSetExtension')
264     ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
265                  'messageSetExtension')
266     golden_text = ('{"messageSet": {'
267                    '    "[%s]": {'
268                    '        "i": 23'
269                    '    },'
270                    '    "[%s]": {'
271                    '        "str": "foo"'
272                    '    }'
273                    '}}') % (ext1_text, ext2_text)
274     self.assertEqual(json.loads(golden_text), json.loads(message_text))
275
276
277   def testJsonEscapeString(self):
278     message = json_format_proto3_pb2.TestMessage()
279     if sys.version_info[0] < 3:
280       message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9'
281     else:
282       message.string_value = '&\n<\"\r>\b\t\f\\\001/'
283       message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8')
284     self.assertEqual(
285         json_format.MessageToJson(message),
286         '{\n  "stringValue": '
287         '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}')
288     parsed_message = json_format_proto3_pb2.TestMessage()
289     self.CheckParseBack(message, parsed_message)
290     text = u'{"int32Value": "\u0031"}'
291     json_format.Parse(text, message)
292     self.assertEqual(message.int32_value, 1)
293
294   def testAlwaysSeriliaze(self):
295     message = json_format_proto3_pb2.TestMessage(
296         string_value='foo')
297     self.assertEqual(
298         json.loads(json_format.MessageToJson(message, True)),
299         json.loads('{'
300                    '"repeatedStringValue": [],'
301                    '"stringValue": "foo",'
302                    '"repeatedBoolValue": [],'
303                    '"repeatedUint32Value": [],'
304                    '"repeatedInt32Value": [],'
305                    '"enumValue": "FOO",'
306                    '"int32Value": 0,'
307                    '"floatValue": 0,'
308                    '"int64Value": "0",'
309                    '"uint32Value": 0,'
310                    '"repeatedBytesValue": [],'
311                    '"repeatedUint64Value": [],'
312                    '"repeatedDoubleValue": [],'
313                    '"bytesValue": "",'
314                    '"boolValue": false,'
315                    '"repeatedEnumValue": [],'
316                    '"uint64Value": "0",'
317                    '"doubleValue": 0,'
318                    '"repeatedFloatValue": [],'
319                    '"repeatedInt64Value": [],'
320                    '"repeatedMessageValue": []}'))
321     parsed_message = json_format_proto3_pb2.TestMessage()
322     self.CheckParseBack(message, parsed_message)
323
324   def testIntegersRepresentedAsFloat(self):
325     message = json_format_proto3_pb2.TestMessage()
326     json_format.Parse('{"int32Value": -2.147483648e9}', message)
327     self.assertEqual(message.int32_value, -2147483648)
328     json_format.Parse('{"int32Value": 1e5}', message)
329     self.assertEqual(message.int32_value, 100000)
330     json_format.Parse('{"int32Value": 1.0}', message)
331     self.assertEqual(message.int32_value, 1)
332
333   def testMapFields(self):
334     message = json_format_proto3_pb2.TestNestedMap()
335     self.assertEqual(
336         json.loads(json_format.MessageToJson(message, True)),
337         json.loads('{'
338                    '"boolMap": {},'
339                    '"int32Map": {},'
340                    '"int64Map": {},'
341                    '"uint32Map": {},'
342                    '"uint64Map": {},'
343                    '"stringMap": {},'
344                    '"mapMap": {}'
345                    '}'))
346     message.bool_map[True] = 1
347     message.bool_map[False] = 2
348     message.int32_map[1] = 2
349     message.int32_map[2] = 3
350     message.int64_map[1] = 2
351     message.int64_map[2] = 3
352     message.uint32_map[1] = 2
353     message.uint32_map[2] = 3
354     message.uint64_map[1] = 2
355     message.uint64_map[2] = 3
356     message.string_map['1'] = 2
357     message.string_map['null'] = 3
358     message.map_map['1'].bool_map[True] = 3
359     self.assertEqual(
360         json.loads(json_format.MessageToJson(message, False)),
361         json.loads('{'
362                    '"boolMap": {"false": 2, "true": 1},'
363                    '"int32Map": {"1": 2, "2": 3},'
364                    '"int64Map": {"1": 2, "2": 3},'
365                    '"uint32Map": {"1": 2, "2": 3},'
366                    '"uint64Map": {"1": 2, "2": 3},'
367                    '"stringMap": {"1": 2, "null": 3},'
368                    '"mapMap": {"1": {"boolMap": {"true": 3}}}'
369                    '}'))
370     parsed_message = json_format_proto3_pb2.TestNestedMap()
371     self.CheckParseBack(message, parsed_message)
372
373   def testOneofFields(self):
374     message = json_format_proto3_pb2.TestOneof()
375     # Always print does not affect oneof fields.
376     self.assertEqual(
377         json_format.MessageToJson(message, True),
378         '{}')
379     message.oneof_int32_value = 0
380     self.assertEqual(
381         json_format.MessageToJson(message, True),
382         '{\n'
383         '  "oneofInt32Value": 0\n'
384         '}')
385     parsed_message = json_format_proto3_pb2.TestOneof()
386     self.CheckParseBack(message, parsed_message)
387
388   def testSurrogates(self):
389     # Test correct surrogate handling.
390     message = json_format_proto3_pb2.TestMessage()
391     json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message)
392     self.assertEqual(message.string_value,
393                      b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict'))
394
395     # Error case: unpaired high surrogate.
396     self.CheckError(
397         '{"stringValue": "\\uD83D"}',
398         r'Invalid \\uXXXX escape|Unpaired.*surrogate')
399
400     # Unpaired low surrogate.
401     self.CheckError(
402         '{"stringValue": "\\uDE01"}',
403         r'Invalid \\uXXXX escape|Unpaired.*surrogate')
404
405   def testTimestampMessage(self):
406     message = json_format_proto3_pb2.TestTimestamp()
407     message.value.seconds = 0
408     message.value.nanos = 0
409     message.repeated_value.add().seconds = 20
410     message.repeated_value[0].nanos = 1
411     message.repeated_value.add().seconds = 0
412     message.repeated_value[1].nanos = 10000
413     message.repeated_value.add().seconds = 100000000
414     message.repeated_value[2].nanos = 0
415     # Maximum time
416     message.repeated_value.add().seconds = 253402300799
417     message.repeated_value[3].nanos = 999999999
418     # Minimum time
419     message.repeated_value.add().seconds = -62135596800
420     message.repeated_value[4].nanos = 0
421     self.assertEqual(
422         json.loads(json_format.MessageToJson(message, True)),
423         json.loads('{'
424                    '"value": "1970-01-01T00:00:00Z",'
425                    '"repeatedValue": ['
426                    '  "1970-01-01T00:00:20.000000001Z",'
427                    '  "1970-01-01T00:00:00.000010Z",'
428                    '  "1973-03-03T09:46:40Z",'
429                    '  "9999-12-31T23:59:59.999999999Z",'
430                    '  "0001-01-01T00:00:00Z"'
431                    ']'
432                    '}'))
433     parsed_message = json_format_proto3_pb2.TestTimestamp()
434     self.CheckParseBack(message, parsed_message)
435     text = (r'{"value": "1970-01-01T00:00:00.01+08:00",'
436             r'"repeatedValue":['
437             r'  "1970-01-01T00:00:00.01+08:30",'
438             r'  "1970-01-01T00:00:00.01-01:23"]}')
439     json_format.Parse(text, parsed_message)
440     self.assertEqual(parsed_message.value.seconds, -8 * 3600)
441     self.assertEqual(parsed_message.value.nanos, 10000000)
442     self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600)
443     self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60)
444
445   def testDurationMessage(self):
446     message = json_format_proto3_pb2.TestDuration()
447     message.value.seconds = 1
448     message.repeated_value.add().seconds = 0
449     message.repeated_value[0].nanos = 10
450     message.repeated_value.add().seconds = -1
451     message.repeated_value[1].nanos = -1000
452     message.repeated_value.add().seconds = 10
453     message.repeated_value[2].nanos = 11000000
454     message.repeated_value.add().seconds = -315576000000
455     message.repeated_value.add().seconds = 315576000000
456     self.assertEqual(
457         json.loads(json_format.MessageToJson(message, True)),
458         json.loads('{'
459                    '"value": "1s",'
460                    '"repeatedValue": ['
461                    '  "0.000000010s",'
462                    '  "-1.000001s",'
463                    '  "10.011s",'
464                    '  "-315576000000s",'
465                    '  "315576000000s"'
466                    ']'
467                    '}'))
468     parsed_message = json_format_proto3_pb2.TestDuration()
469     self.CheckParseBack(message, parsed_message)
470
471   def testFieldMaskMessage(self):
472     message = json_format_proto3_pb2.TestFieldMask()
473     message.value.paths.append('foo.bar')
474     message.value.paths.append('bar')
475     self.assertEqual(
476         json_format.MessageToJson(message, True),
477         '{\n'
478         '  "value": "foo.bar,bar"\n'
479         '}')
480     parsed_message = json_format_proto3_pb2.TestFieldMask()
481     self.CheckParseBack(message, parsed_message)
482
483     message.value.Clear()
484     self.assertEqual(
485         json_format.MessageToJson(message, True),
486         '{\n'
487         '  "value": ""\n'
488         '}')
489     self.CheckParseBack(message, parsed_message)
490
491   def testWrapperMessage(self):
492     message = json_format_proto3_pb2.TestWrapper()
493     message.bool_value.value = False
494     message.int32_value.value = 0
495     message.string_value.value = ''
496     message.bytes_value.value = b''
497     message.repeated_bool_value.add().value = True
498     message.repeated_bool_value.add().value = False
499     message.repeated_int32_value.add()
500     self.assertEqual(
501         json.loads(json_format.MessageToJson(message, True)),
502         json.loads('{\n'
503                    '  "int32Value": 0,'
504                    '  "boolValue": false,'
505                    '  "stringValue": "",'
506                    '  "bytesValue": "",'
507                    '  "repeatedBoolValue": [true, false],'
508                    '  "repeatedInt32Value": [0],'
509                    '  "repeatedUint32Value": [],'
510                    '  "repeatedFloatValue": [],'
511                    '  "repeatedDoubleValue": [],'
512                    '  "repeatedBytesValue": [],'
513                    '  "repeatedInt64Value": [],'
514                    '  "repeatedUint64Value": [],'
515                    '  "repeatedStringValue": []'
516                    '}'))
517     parsed_message = json_format_proto3_pb2.TestWrapper()
518     self.CheckParseBack(message, parsed_message)
519
520   def testStructMessage(self):
521     message = json_format_proto3_pb2.TestStruct()
522     message.value['name'] = 'Jim'
523     message.value['age'] = 10
524     message.value['attend'] = True
525     message.value['email'] = None
526     message.value.get_or_create_struct('address')['city'] = 'SFO'
527     message.value['address']['house_number'] = 1024
528     message.value.get_or_create_struct('empty_struct')
529     message.value.get_or_create_list('empty_list')
530     struct_list = message.value.get_or_create_list('list')
531     struct_list.extend([6, 'seven', True, False, None])
532     struct_list.add_struct()['subkey2'] = 9
533     message.repeated_value.add()['age'] = 11
534     message.repeated_value.add()
535     self.assertEqual(
536         json.loads(json_format.MessageToJson(message, False)),
537         json.loads(
538             '{'
539             '  "value": {'
540             '    "address": {'
541             '      "city": "SFO", '
542             '      "house_number": 1024'
543             '    }, '
544             '    "empty_struct": {}, '
545             '    "empty_list": [], '
546             '    "age": 10, '
547             '    "name": "Jim", '
548             '    "attend": true, '
549             '    "email": null, '
550             '    "list": [6, "seven", true, false, null, {"subkey2": 9}]'
551             '  },'
552             '  "repeatedValue": [{"age": 11}, {}]'
553             '}'))
554     parsed_message = json_format_proto3_pb2.TestStruct()
555     self.CheckParseBack(message, parsed_message)
556     # check for regression; this used to raise
557     parsed_message.value['empty_struct']
558     parsed_message.value['empty_list']
559
560   def testValueMessage(self):
561     message = json_format_proto3_pb2.TestValue()
562     message.value.string_value = 'hello'
563     message.repeated_value.add().number_value = 11.1
564     message.repeated_value.add().bool_value = False
565     message.repeated_value.add().null_value = 0
566     self.assertEqual(
567         json.loads(json_format.MessageToJson(message, False)),
568         json.loads(
569             '{'
570             '  "value": "hello",'
571             '  "repeatedValue": [11.1, false, null]'
572             '}'))
573     parsed_message = json_format_proto3_pb2.TestValue()
574     self.CheckParseBack(message, parsed_message)
575     # Can't parse back if the Value message is not set.
576     message.repeated_value.add()
577     self.assertEqual(
578         json.loads(json_format.MessageToJson(message, False)),
579         json.loads(
580             '{'
581             '  "value": "hello",'
582             '  "repeatedValue": [11.1, false, null, null]'
583             '}'))
584     message.Clear()
585     json_format.Parse('{"value": null}', message)
586     self.assertEqual(message.value.WhichOneof('kind'), 'null_value')
587
588   def testListValueMessage(self):
589     message = json_format_proto3_pb2.TestListValue()
590     message.value.values.add().number_value = 11.1
591     message.value.values.add().null_value = 0
592     message.value.values.add().bool_value = True
593     message.value.values.add().string_value = 'hello'
594     message.value.values.add().struct_value['name'] = 'Jim'
595     message.repeated_value.add().values.add().number_value = 1
596     message.repeated_value.add()
597     self.assertEqual(
598         json.loads(json_format.MessageToJson(message, False)),
599         json.loads(
600             '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,'
601             '"repeatedValue": [[1], []]}'))
602     parsed_message = json_format_proto3_pb2.TestListValue()
603     self.CheckParseBack(message, parsed_message)
604
605   def testAnyMessage(self):
606     message = json_format_proto3_pb2.TestAny()
607     value1 = json_format_proto3_pb2.MessageType()
608     value2 = json_format_proto3_pb2.MessageType()
609     value1.value = 1234
610     value2.value = 5678
611     message.value.Pack(value1)
612     message.repeated_value.add().Pack(value1)
613     message.repeated_value.add().Pack(value2)
614     message.repeated_value.add()
615     self.assertEqual(
616         json.loads(json_format.MessageToJson(message, True)),
617         json.loads(
618             '{\n'
619             '  "repeatedValue": [ {\n'
620             '    "@type": "type.googleapis.com/proto3.MessageType",\n'
621             '    "value": 1234\n'
622             '  }, {\n'
623             '    "@type": "type.googleapis.com/proto3.MessageType",\n'
624             '    "value": 5678\n'
625             '  },\n'
626             '  {}],\n'
627             '  "value": {\n'
628             '    "@type": "type.googleapis.com/proto3.MessageType",\n'
629             '    "value": 1234\n'
630             '  }\n'
631             '}\n'))
632     parsed_message = json_format_proto3_pb2.TestAny()
633     self.CheckParseBack(message, parsed_message)
634     # Must print @type first
635     test_message = json_format_proto3_pb2.TestMessage(
636         bool_value=True,
637         int32_value=20,
638         int64_value=-20,
639         uint32_value=20,
640         uint64_value=20,
641         double_value=3.14,
642         string_value='foo')
643     message.Clear()
644     message.value.Pack(test_message)
645     self.assertEqual(
646         json_format.MessageToJson(message, False)[0:68],
647         '{\n'
648         '  "value": {\n'
649         '    "@type": "type.googleapis.com/proto3.TestMessage"')
650
651   def testAnyMessageDescriptorPoolMissingType(self):
652     packed_message = unittest_pb2.OneString()
653     packed_message.data = 'string'
654     message = any_test_pb2.TestAny()
655     message.any_value.Pack(packed_message)
656     empty_pool = descriptor_pool.DescriptorPool()
657     with self.assertRaises(TypeError) as cm:
658       json_format.MessageToJson(message, True, descriptor_pool=empty_pool)
659     self.assertEqual(
660         'Can not find message descriptor by type_url:'
661         ' type.googleapis.com/protobuf_unittest.OneString.',
662         str(cm.exception))
663
664   def testWellKnownInAnyMessage(self):
665     message = any_pb2.Any()
666     int32_value = wrappers_pb2.Int32Value()
667     int32_value.value = 1234
668     message.Pack(int32_value)
669     self.assertEqual(
670         json.loads(json_format.MessageToJson(message, True)),
671         json.loads(
672             '{\n'
673             '  "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n'
674             '  "value": 1234\n'
675             '}\n'))
676     parsed_message = any_pb2.Any()
677     self.CheckParseBack(message, parsed_message)
678
679     timestamp = timestamp_pb2.Timestamp()
680     message.Pack(timestamp)
681     self.assertEqual(
682         json.loads(json_format.MessageToJson(message, True)),
683         json.loads(
684             '{\n'
685             '  "@type": "type.googleapis.com/google.protobuf.Timestamp",\n'
686             '  "value": "1970-01-01T00:00:00Z"\n'
687             '}\n'))
688     self.CheckParseBack(message, parsed_message)
689
690     duration = duration_pb2.Duration()
691     duration.seconds = 1
692     message.Pack(duration)
693     self.assertEqual(
694         json.loads(json_format.MessageToJson(message, True)),
695         json.loads(
696             '{\n'
697             '  "@type": "type.googleapis.com/google.protobuf.Duration",\n'
698             '  "value": "1s"\n'
699             '}\n'))
700     self.CheckParseBack(message, parsed_message)
701
702     field_mask = field_mask_pb2.FieldMask()
703     field_mask.paths.append('foo.bar')
704     field_mask.paths.append('bar')
705     message.Pack(field_mask)
706     self.assertEqual(
707         json.loads(json_format.MessageToJson(message, True)),
708         json.loads(
709             '{\n'
710             '  "@type": "type.googleapis.com/google.protobuf.FieldMask",\n'
711             '  "value": "foo.bar,bar"\n'
712             '}\n'))
713     self.CheckParseBack(message, parsed_message)
714
715     struct_message = struct_pb2.Struct()
716     struct_message['name'] = 'Jim'
717     message.Pack(struct_message)
718     self.assertEqual(
719         json.loads(json_format.MessageToJson(message, True)),
720         json.loads(
721             '{\n'
722             '  "@type": "type.googleapis.com/google.protobuf.Struct",\n'
723             '  "value": {"name": "Jim"}\n'
724             '}\n'))
725     self.CheckParseBack(message, parsed_message)
726
727     nested_any = any_pb2.Any()
728     int32_value.value = 5678
729     nested_any.Pack(int32_value)
730     message.Pack(nested_any)
731     self.assertEqual(
732         json.loads(json_format.MessageToJson(message, True)),
733         json.loads(
734             '{\n'
735             '  "@type": "type.googleapis.com/google.protobuf.Any",\n'
736             '  "value": {\n'
737             '    "@type": "type.googleapis.com/google.protobuf.Int32Value",\n'
738             '    "value": 5678\n'
739             '  }\n'
740             '}\n'))
741     self.CheckParseBack(message, parsed_message)
742
743   def testParseNull(self):
744     message = json_format_proto3_pb2.TestMessage()
745     parsed_message = json_format_proto3_pb2.TestMessage()
746     self.FillAllFields(parsed_message)
747     json_format.Parse('{"int32Value": null, '
748                       '"int64Value": null, '
749                       '"uint32Value": null,'
750                       '"uint64Value": null,'
751                       '"floatValue": null,'
752                       '"doubleValue": null,'
753                       '"boolValue": null,'
754                       '"stringValue": null,'
755                       '"bytesValue": null,'
756                       '"messageValue": null,'
757                       '"enumValue": null,'
758                       '"repeatedInt32Value": null,'
759                       '"repeatedInt64Value": null,'
760                       '"repeatedUint32Value": null,'
761                       '"repeatedUint64Value": null,'
762                       '"repeatedFloatValue": null,'
763                       '"repeatedDoubleValue": null,'
764                       '"repeatedBoolValue": null,'
765                       '"repeatedStringValue": null,'
766                       '"repeatedBytesValue": null,'
767                       '"repeatedMessageValue": null,'
768                       '"repeatedEnumValue": null'
769                       '}',
770                       parsed_message)
771     self.assertEqual(message, parsed_message)
772     # Null and {} should have different behavior for sub message.
773     self.assertFalse(parsed_message.HasField('message_value'))
774     json_format.Parse('{"messageValue": {}}', parsed_message)
775     self.assertTrue(parsed_message.HasField('message_value'))
776     # Null is not allowed to be used as an element in repeated field.
777     self.assertRaisesRegexp(
778         json_format.ParseError,
779         'Failed to parse repeatedInt32Value field: '
780         'null is not allowed to be used as an element in a repeated field.',
781         json_format.Parse,
782         '{"repeatedInt32Value":[1, null]}',
783         parsed_message)
784     self.CheckError('{"repeatedMessageValue":[null]}',
785                     'Failed to parse repeatedMessageValue field: null is not'
786                     ' allowed to be used as an element in a repeated field.')
787
788   def testNanFloat(self):
789     message = json_format_proto3_pb2.TestMessage()
790     message.float_value = float('nan')
791     text = '{\n  "floatValue": "NaN"\n}'
792     self.assertEqual(json_format.MessageToJson(message), text)
793     parsed_message = json_format_proto3_pb2.TestMessage()
794     json_format.Parse(text, parsed_message)
795     self.assertTrue(math.isnan(parsed_message.float_value))
796
797   def testParseDoubleToFloat(self):
798     message = json_format_proto3_pb2.TestMessage()
799     text = ('{"repeatedFloatValue": [3.4028235e+39, 1.4028235e-39]\n}')
800     json_format.Parse(text, message)
801     self.assertEqual(message.repeated_float_value[0], float('inf'))
802     self.assertAlmostEqual(message.repeated_float_value[1], 1.4028235e-39)
803
804   def testParseEmptyText(self):
805     self.CheckError('',
806                     r'Failed to load JSON: (Expecting value)|(No JSON).')
807
808   def testParseEnumValue(self):
809     message = json_format_proto3_pb2.TestMessage()
810     text = '{"enumValue": 0}'
811     json_format.Parse(text, message)
812     text = '{"enumValue": 1}'
813     json_format.Parse(text, message)
814     self.CheckError(
815         '{"enumValue": "baz"}',
816         'Failed to parse enumValue field: Invalid enum value baz '
817         'for enum type proto3.EnumType.')
818     # Proto3 accepts numeric unknown enums.
819     text = '{"enumValue": 12345}'
820     json_format.Parse(text, message)
821     # Proto2 does not accept unknown enums.
822     message = unittest_pb2.TestAllTypes()
823     self.assertRaisesRegexp(
824         json_format.ParseError,
825         'Failed to parse optionalNestedEnum field: Invalid enum value 12345 '
826         'for enum type protobuf_unittest.TestAllTypes.NestedEnum.',
827         json_format.Parse, '{"optionalNestedEnum": 12345}', message)
828
829   def testParseBadIdentifer(self):
830     self.CheckError('{int32Value: 1}',
831                     (r'Failed to load JSON: Expecting property name'
832                      r'( enclosed in double quotes)?: line 1'))
833     self.CheckError('{"unknownName": 1}',
834                     'Message type "proto3.TestMessage" has no field named '
835                     '"unknownName".')
836
837   def testIgnoreUnknownField(self):
838     text = '{"unknownName": 1}'
839     parsed_message = json_format_proto3_pb2.TestMessage()
840     json_format.Parse(text, parsed_message, ignore_unknown_fields=True)
841     text = ('{\n'
842             '  "repeatedValue": [ {\n'
843             '    "@type": "type.googleapis.com/proto3.MessageType",\n'
844             '    "unknownName": 1\n'
845             '  }]\n'
846             '}\n')
847     parsed_message = json_format_proto3_pb2.TestAny()
848     json_format.Parse(text, parsed_message, ignore_unknown_fields=True)
849
850   def testDuplicateField(self):
851     self.CheckError('{"int32Value": 1,\n"int32Value":2}',
852                     'Failed to load JSON: duplicate key int32Value.')
853
854   def testInvalidBoolValue(self):
855     self.CheckError('{"boolValue": 1}',
856                     'Failed to parse boolValue field: '
857                     'Expected true or false without quotes.')
858     self.CheckError('{"boolValue": "true"}',
859                     'Failed to parse boolValue field: '
860                     'Expected true or false without quotes.')
861
862   def testInvalidIntegerValue(self):
863     message = json_format_proto3_pb2.TestMessage()
864     text = '{"int32Value": 0x12345}'
865     self.assertRaises(json_format.ParseError,
866                       json_format.Parse, text, message)
867     self.CheckError('{"int32Value": 1.5}',
868                     'Failed to parse int32Value field: '
869                     'Couldn\'t parse integer: 1.5.')
870     self.CheckError('{"int32Value": 012345}',
871                     (r'Failed to load JSON: Expecting \'?,\'? delimiter: '
872                      r'line 1.'))
873     self.CheckError('{"int32Value": " 1 "}',
874                     'Failed to parse int32Value field: '
875                     'Couldn\'t parse integer: " 1 ".')
876     self.CheckError('{"int32Value": "1 "}',
877                     'Failed to parse int32Value field: '
878                     'Couldn\'t parse integer: "1 ".')
879     self.CheckError('{"int32Value": 12345678901234567890}',
880                     'Failed to parse int32Value field: Value out of range: '
881                     '12345678901234567890.')
882     self.CheckError('{"uint32Value": -1}',
883                     'Failed to parse uint32Value field: '
884                     'Value out of range: -1.')
885
886   def testInvalidFloatValue(self):
887     self.CheckError('{"floatValue": "nan"}',
888                     'Failed to parse floatValue field: Couldn\'t '
889                     'parse float "nan", use "NaN" instead.')
890
891   def testInvalidBytesValue(self):
892     self.CheckError('{"bytesValue": "AQI"}',
893                     'Failed to parse bytesValue field: Incorrect padding.')
894     self.CheckError('{"bytesValue": "AQI*"}',
895                     'Failed to parse bytesValue field: Incorrect padding.')
896
897   def testInvalidRepeated(self):
898     self.CheckError('{"repeatedInt32Value": 12345}',
899                     (r'Failed to parse repeatedInt32Value field: repeated field'
900                      r' repeatedInt32Value must be in \[\] which is 12345.'))
901
902   def testInvalidMap(self):
903     message = json_format_proto3_pb2.TestMap()
904     text = '{"int32Map": {"null": 2, "2": 3}}'
905     self.assertRaisesRegexp(
906         json_format.ParseError,
907         'Failed to parse int32Map field: invalid literal',
908         json_format.Parse, text, message)
909     text = '{"int32Map": {1: 2, "2": 3}}'
910     self.assertRaisesRegexp(
911         json_format.ParseError,
912         (r'Failed to load JSON: Expecting property name'
913          r'( enclosed in double quotes)?: line 1'),
914         json_format.Parse, text, message)
915     text = '{"boolMap": {"null": 1}}'
916     self.assertRaisesRegexp(
917         json_format.ParseError,
918         'Failed to parse boolMap field: Expected "true" or "false", not null.',
919         json_format.Parse, text, message)
920     if sys.version_info < (2, 7):
921       return
922     text = r'{"stringMap": {"a": 3, "\u0061": 2}}'
923     self.assertRaisesRegexp(
924         json_format.ParseError,
925         'Failed to load JSON: duplicate key a',
926         json_format.Parse, text, message)
927     text = r'{"stringMap": 0}'
928     self.assertRaisesRegexp(
929         json_format.ParseError,
930         'Failed to parse stringMap field: Map field string_map must be '
931         'in a dict which is 0.',
932         json_format.Parse, text, message)
933
934   def testInvalidTimestamp(self):
935     message = json_format_proto3_pb2.TestTimestamp()
936     text = '{"value": "10000-01-01T00:00:00.00Z"}'
937     self.assertRaisesRegexp(
938         json_format.ParseError,
939         'Failed to parse value field: '
940         'time data \'10000-01-01T00:00:00\' does not match'
941         ' format \'%Y-%m-%dT%H:%M:%S\'.',
942         json_format.Parse, text, message)
943     text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}'
944     self.assertRaisesRegexp(
945         json_format.ParseError,
946         'nanos 0123456789012 more than 9 fractional digits.',
947         json_format.Parse, text, message)
948     text = '{"value": "1972-01-01T01:00:00.01+08"}'
949     self.assertRaisesRegexp(
950         json_format.ParseError,
951         (r'Invalid timezone offset value: \+08.'),
952         json_format.Parse, text, message)
953     # Time smaller than minimum time.
954     text = '{"value": "0000-01-01T00:00:00Z"}'
955     self.assertRaisesRegexp(
956         json_format.ParseError,
957         'Failed to parse value field: year (0 )?is out of range.',
958         json_format.Parse, text, message)
959     # Time bigger than maxinum time.
960     message.value.seconds = 253402300800
961     self.assertRaisesRegexp(
962         OverflowError,
963         'date value out of range',
964         json_format.MessageToJson, message)
965
966   def testInvalidOneof(self):
967     message = json_format_proto3_pb2.TestOneof()
968     text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}'
969     self.assertRaisesRegexp(
970         json_format.ParseError,
971         'Message type "proto3.TestOneof"'
972         ' should not have multiple "oneof_value" oneof fields.',
973         json_format.Parse, text, message)
974
975   def testInvalidListValue(self):
976     message = json_format_proto3_pb2.TestListValue()
977     text = '{"value": 1234}'
978     self.assertRaisesRegexp(
979         json_format.ParseError,
980         r'Failed to parse value field: ListValue must be in \[\] which is 1234',
981         json_format.Parse, text, message)
982
983   def testInvalidStruct(self):
984     message = json_format_proto3_pb2.TestStruct()
985     text = '{"value": 1234}'
986     self.assertRaisesRegexp(
987         json_format.ParseError,
988         'Failed to parse value field: Struct must be in a dict which is 1234',
989         json_format.Parse, text, message)
990
991   def testInvalidAny(self):
992     message = any_pb2.Any()
993     text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}'
994     self.assertRaisesRegexp(
995         KeyError,
996         'value',
997         json_format.Parse, text, message)
998     text = '{"value": 1234}'
999     self.assertRaisesRegexp(
1000         json_format.ParseError,
1001         '@type is missing when parsing any message.',
1002         json_format.Parse, text, message)
1003     text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}'
1004     self.assertRaisesRegexp(
1005         TypeError,
1006         'Can not find message descriptor by type_url: '
1007         'type.googleapis.com/MessageNotExist.',
1008         json_format.Parse, text, message)
1009     # Only last part is to be used: b/25630112
1010     text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",'
1011             r'"value": 1234}')
1012     json_format.Parse(text, message)
1013
1014   def testPreservingProtoFieldNames(self):
1015     message = json_format_proto3_pb2.TestMessage()
1016     message.int32_value = 12345
1017     self.assertEqual('{\n  "int32Value": 12345\n}',
1018                      json_format.MessageToJson(message))
1019     self.assertEqual('{\n  "int32_value": 12345\n}',
1020                      json_format.MessageToJson(message, False, True))
1021     # When including_default_value_fields is True.
1022     message = json_format_proto3_pb2.TestTimestamp()
1023     self.assertEqual('{\n  "repeatedValue": []\n}',
1024                      json_format.MessageToJson(message, True, False))
1025     self.assertEqual('{\n  "repeated_value": []\n}',
1026                      json_format.MessageToJson(message, True, True))
1027
1028     # Parsers accept both original proto field names and lowerCamelCase names.
1029     message = json_format_proto3_pb2.TestMessage()
1030     json_format.Parse('{"int32Value": 54321}', message)
1031     self.assertEqual(54321, message.int32_value)
1032     json_format.Parse('{"int32_value": 12345}', message)
1033     self.assertEqual(12345, message.int32_value)
1034
1035   def testIndent(self):
1036     message = json_format_proto3_pb2.TestMessage()
1037     message.int32_value = 12345
1038     self.assertEqual('{\n"int32Value": 12345\n}',
1039                      json_format.MessageToJson(message, indent=0))
1040
1041   def testFormatEnumsAsInts(self):
1042     message = json_format_proto3_pb2.TestMessage()
1043     message.enum_value = json_format_proto3_pb2.BAR
1044     message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
1045     message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
1046     self.assertEqual(json.loads('{\n'
1047                                 '  "enumValue": 1,\n'
1048                                 '  "repeatedEnumValue": [0, 1]\n'
1049                                 '}\n'),
1050                      json.loads(json_format.MessageToJson(
1051                          message, use_integers_for_enums=True)))
1052
1053   def testParseDict(self):
1054     expected = 12345
1055     js_dict = {'int32Value': expected}
1056     message = json_format_proto3_pb2.TestMessage()
1057     json_format.ParseDict(js_dict, message)
1058     self.assertEqual(expected, message.int32_value)
1059
1060   def testParseDictAnyDescriptorPoolMissingType(self):
1061     # Confirm that ParseDict does not raise ParseError with default pool
1062     js_dict = {
1063         'any_value': {
1064             '@type': 'type.googleapis.com/proto3.MessageType',
1065             'value': 1234
1066         }
1067     }
1068     json_format.ParseDict(js_dict, any_test_pb2.TestAny())
1069     # Check ParseDict raises ParseError with empty pool
1070     js_dict = {
1071         'any_value': {
1072             '@type': 'type.googleapis.com/proto3.MessageType',
1073             'value': 1234
1074         }
1075     }
1076     with self.assertRaises(json_format.ParseError) as cm:
1077       empty_pool = descriptor_pool.DescriptorPool()
1078       json_format.ParseDict(js_dict,
1079                             any_test_pb2.TestAny(),
1080                             descriptor_pool=empty_pool)
1081     self.assertEqual(
1082         str(cm.exception),
1083         'Failed to parse any_value field: Can not find message descriptor by'
1084         ' type_url: type.googleapis.com/proto3.MessageType..')
1085
1086   def testMessageToDict(self):
1087     message = json_format_proto3_pb2.TestMessage()
1088     message.int32_value = 12345
1089     expected = {'int32Value': 12345}
1090     self.assertEqual(expected,
1091                      json_format.MessageToDict(message))
1092
1093   def testJsonName(self):
1094     message = json_format_proto3_pb2.TestCustomJsonName()
1095     message.value = 12345
1096     self.assertEqual('{\n  "@value": 12345\n}',
1097                      json_format.MessageToJson(message))
1098     parsed_message = json_format_proto3_pb2.TestCustomJsonName()
1099     self.CheckParseBack(message, parsed_message)
1100
1101   def testSortKeys(self):
1102     # Testing sort_keys is not perfectly working, as by random luck we could
1103     # get the output sorted. We just use a selection of names.
1104     message = json_format_proto3_pb2.TestMessage(bool_value=True,
1105                                                  int32_value=1,
1106                                                  int64_value=3,
1107                                                  uint32_value=4,
1108                                                  string_value='bla')
1109     self.assertEqual(
1110         json_format.MessageToJson(message, sort_keys=True),
1111         # We use json.dumps() instead of a hardcoded string due to differences
1112         # between Python 2 and Python 3.
1113         json.dumps({'boolValue': True, 'int32Value': 1, 'int64Value': '3',
1114                     'uint32Value': 4, 'stringValue': 'bla'},
1115                    indent=2, sort_keys=True))
1116
1117
1118 if __name__ == '__main__':
1119   unittest.main()