1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# 4# Use of this source code is governed by a BSD-style 5# license that can be found in the LICENSE file or at 6# https://developers.google.com/open-source/licenses/bsd 7 8"""Test for google.protobuf.json_format.""" 9 10__author__ = 'jieluo@google.com (Jie Luo)' 11 12import json 13import math 14import struct 15import unittest 16 17from google.protobuf import descriptor_pool 18from google.protobuf import json_format 19from google.protobuf.internal import more_messages_pb2 20from google.protobuf.internal import test_proto2_pb2 21from google.protobuf.internal import test_proto3_optional_pb2 22 23from google.protobuf import any_pb2 24from google.protobuf import duration_pb2 25from google.protobuf import field_mask_pb2 26from google.protobuf import struct_pb2 27from google.protobuf import timestamp_pb2 28from google.protobuf import wrappers_pb2 29from google.protobuf import any_test_pb2 30from google.protobuf import unittest_mset_pb2 31from google.protobuf import unittest_pb2 32from google.protobuf.util import json_format_pb2 33from google.protobuf.util import json_format_proto3_pb2 34 35 36class JsonFormatBase(unittest.TestCase): 37 38 def FillAllFields(self, message): 39 message.int32_value = 20 40 message.int64_value = -20 41 message.uint32_value = 3120987654 42 message.uint64_value = 12345678900 43 message.float_value = float('-inf') 44 message.double_value = 3.1415 45 message.bool_value = True 46 message.string_value = 'foo' 47 message.bytes_value = b'bar' 48 message.message_value.value = 10 49 message.enum_value = json_format_proto3_pb2.BAR 50 # Repeated 51 message.repeated_int32_value.append(0x7FFFFFFF) 52 message.repeated_int32_value.append(-2147483648) 53 message.repeated_int64_value.append(9007199254740992) 54 message.repeated_int64_value.append(-9007199254740992) 55 message.repeated_uint32_value.append(0xFFFFFFF) 56 message.repeated_uint32_value.append(0x7FFFFFF) 57 message.repeated_uint64_value.append(9007199254740992) 58 message.repeated_uint64_value.append(9007199254740991) 59 message.repeated_float_value.append(0) 60 61 message.repeated_double_value.append(1e-15) 62 message.repeated_double_value.append(float('inf')) 63 message.repeated_bool_value.append(True) 64 message.repeated_bool_value.append(False) 65 message.repeated_string_value.append('Few symbols!#$,;') 66 message.repeated_string_value.append('bar') 67 message.repeated_bytes_value.append(b'foo') 68 message.repeated_bytes_value.append(b'bar') 69 message.repeated_message_value.add().value = 10 70 message.repeated_message_value.add().value = 11 71 message.repeated_enum_value.append(json_format_proto3_pb2.FOO) 72 message.repeated_enum_value.append(json_format_proto3_pb2.BAR) 73 self.message = message 74 75 def CheckParseBack(self, message, parsed_message): 76 json_format.Parse(json_format.MessageToJson(message), parsed_message) 77 self.assertEqual(message, parsed_message) 78 79 def CheckError(self, text, error_message): 80 message = json_format_proto3_pb2.TestMessage() 81 self.assertRaisesRegex( 82 json_format.ParseError, error_message, json_format.Parse, text, message 83 ) 84 85 86class JsonFormatTest(JsonFormatBase): 87 88 def testEmptyMessageToJson(self): 89 message = json_format_proto3_pb2.TestMessage() 90 self.assertEqual(json_format.MessageToJson(message), '{}') 91 parsed_message = json_format_proto3_pb2.TestMessage() 92 self.CheckParseBack(message, parsed_message) 93 94 def testPartialMessageToJson(self): 95 message = json_format_proto3_pb2.TestMessage( 96 string_value='test', repeated_int32_value=[89, 4] 97 ) 98 self.assertEqual( 99 json.loads(json_format.MessageToJson(message)), 100 json.loads('{"stringValue": "test", "repeatedInt32Value": [89, 4]}'), 101 ) 102 parsed_message = json_format_proto3_pb2.TestMessage() 103 self.CheckParseBack(message, parsed_message) 104 105 def testAllFieldsToJson(self): 106 message = json_format_proto3_pb2.TestMessage() 107 text = ( 108 '{"int32Value": 20, ' 109 '"int64Value": "-20", ' 110 '"uint32Value": 3120987654,' 111 '"uint64Value": "12345678900",' 112 '"floatValue": "-Infinity",' 113 '"doubleValue": 3.1415,' 114 '"boolValue": true,' 115 '"stringValue": "foo",' 116 '"bytesValue": "YmFy",' 117 '"messageValue": {"value": 10},' 118 '"enumValue": "BAR",' 119 '"repeatedInt32Value": [2147483647, -2147483648],' 120 '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],' 121 '"repeatedUint32Value": [268435455, 134217727],' 122 '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],' 123 '"repeatedFloatValue": [0],' 124 '"repeatedDoubleValue": [1e-15, "Infinity"],' 125 '"repeatedBoolValue": [true, false],' 126 '"repeatedStringValue": ["Few symbols!#$,;", "bar"],' 127 '"repeatedBytesValue": ["Zm9v", "YmFy"],' 128 '"repeatedMessageValue": [{"value": 10}, {"value": 11}],' 129 '"repeatedEnumValue": ["FOO", "BAR"]' 130 '}' 131 ) 132 self.FillAllFields(message) 133 self.assertEqual( 134 json.loads(json_format.MessageToJson(message)), json.loads(text) 135 ) 136 parsed_message = json_format_proto3_pb2.TestMessage() 137 json_format.Parse(text, parsed_message) 138 self.assertEqual(message, parsed_message) 139 140 def testUnknownEnumToJsonAndBack(self): 141 text = '{\n "enumValue": 999\n}' 142 message = json_format_proto3_pb2.TestMessage() 143 message.enum_value = 999 144 self.assertEqual(json_format.MessageToJson(message), text) 145 parsed_message = json_format_proto3_pb2.TestMessage() 146 json_format.Parse(text, parsed_message) 147 self.assertEqual(message, parsed_message) 148 149 def testExtensionToJsonAndBack(self): 150 message = unittest_mset_pb2.TestMessageSetContainer() 151 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension 152 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension 153 message.message_set.Extensions[ext1].i = 23 154 message.message_set.Extensions[ext2].str = 'foo' 155 message_text = json_format.MessageToJson(message) 156 parsed_message = unittest_mset_pb2.TestMessageSetContainer() 157 json_format.Parse(message_text, parsed_message) 158 self.assertEqual(message, parsed_message) 159 160 def testExtensionErrors(self): 161 self.CheckError( 162 '{"[extensionField]": {}}', 163 'Message type proto3.TestMessage does not have extensions', 164 ) 165 166 def testExtensionToDictAndBack(self): 167 message = unittest_mset_pb2.TestMessageSetContainer() 168 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension 169 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension 170 message.message_set.Extensions[ext1].i = 23 171 message.message_set.Extensions[ext2].str = 'foo' 172 message_dict = json_format.MessageToDict(message) 173 parsed_message = unittest_mset_pb2.TestMessageSetContainer() 174 json_format.ParseDict(message_dict, parsed_message) 175 self.assertEqual(message, parsed_message) 176 177 def testExtensionToDictAndBackWithScalar(self): 178 message = unittest_pb2.TestAllExtensions() 179 ext1 = unittest_pb2.TestNestedExtension.test 180 message.Extensions[ext1] = 'data' 181 message_dict = json_format.MessageToDict(message) 182 parsed_message = unittest_pb2.TestAllExtensions() 183 json_format.ParseDict(message_dict, parsed_message) 184 self.assertEqual(message, parsed_message) 185 186 def testJsonParseDictToAnyDoesNotAlterInput(self): 187 orig_dict = { 188 'int32Value': 20, 189 '@type': 'type.googleapis.com/proto3.TestMessage', 190 } 191 copied_dict = json.loads(json.dumps(orig_dict)) 192 parsed_message = any_pb2.Any() 193 json_format.ParseDict(copied_dict, parsed_message) 194 self.assertEqual(copied_dict, orig_dict) 195 196 def testExtensionSerializationDictMatchesProto3Spec(self): 197 """See go/proto3-json-spec for spec.""" 198 message = unittest_mset_pb2.TestMessageSetContainer() 199 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension 200 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension 201 message.message_set.Extensions[ext1].i = 23 202 message.message_set.Extensions[ext2].str = 'foo' 203 message_dict = json_format.MessageToDict(message) 204 golden_dict = { 205 'messageSet': { 206 '[protobuf_unittest.TestMessageSetExtension1.message_set_extension]': { 207 'i': 23, 208 }, 209 '[protobuf_unittest.TestMessageSetExtension2.message_set_extension]': { 210 'str': 'foo', 211 }, 212 }, 213 } 214 self.assertEqual(golden_dict, message_dict) 215 parsed_msg = unittest_mset_pb2.TestMessageSetContainer() 216 json_format.ParseDict(golden_dict, parsed_msg) 217 self.assertEqual(message, parsed_msg) 218 219 def testExtensionSerializationDictMatchesProto3SpecMore(self): 220 """See go/proto3-json-spec for spec.""" 221 message = json_format_pb2.TestMessageWithExtension() 222 ext = json_format_pb2.TestExtension.ext 223 message.Extensions[ext].value = 'stuff' 224 message_dict = json_format.MessageToDict(message) 225 expected_dict = { 226 '[protobuf_unittest.TestExtension.ext]': { 227 'value': 'stuff', 228 }, 229 } 230 self.assertEqual(expected_dict, message_dict) 231 232 def testExtensionSerializationJsonMatchesProto3Spec(self): 233 """See go/proto3-json-spec for spec.""" 234 message = unittest_mset_pb2.TestMessageSetContainer() 235 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension 236 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension 237 message.message_set.Extensions[ext1].i = 23 238 message.message_set.Extensions[ext2].str = 'foo' 239 message_text = json_format.MessageToJson(message) 240 ext1_text = 'protobuf_unittest.TestMessageSetExtension1.message_set_extension' 241 ext2_text = 'protobuf_unittest.TestMessageSetExtension2.message_set_extension' 242 golden_text = ( 243 '{"messageSet": {' 244 ' "[%s]": {' 245 ' "i": 23' 246 ' },' 247 ' "[%s]": {' 248 ' "str": "foo"' 249 ' }' 250 '}}' 251 ) % (ext1_text, ext2_text) 252 self.assertEqual(json.loads(golden_text), json.loads(message_text)) 253 254 def testJsonEscapeString(self): 255 message = json_format_proto3_pb2.TestMessage() 256 message.string_value = '&\n<"\r>\b\t\f\\\001/' 257 message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8') 258 self.assertEqual( 259 json_format.MessageToJson(message), 260 '{\n "stringValue": ' 261 '"&\\n<\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}', 262 ) 263 parsed_message = json_format_proto3_pb2.TestMessage() 264 self.CheckParseBack(message, parsed_message) 265 text = '{"int32Value": "\u0031"}' 266 json_format.Parse(text, message) 267 self.assertEqual(message.int32_value, 1) 268 269 def testProto3Optional_IncludingDefaultValueWithoutPresenceFields(self): 270 message = test_proto3_optional_pb2.TestProto3Optional() 271 self.assertEqual( 272 json.loads( 273 json_format.MessageToJson( 274 message, always_print_fields_with_no_presence=True 275 ) 276 ), 277 json.loads('{"repeatedInt32": [], "repeatedNestedMessage": []}'), 278 ) 279 message.optional_int32 = 0 280 self.assertEqual( 281 json.loads( 282 json_format.MessageToJson( 283 message, always_print_fields_with_no_presence=True 284 ) 285 ), 286 json.loads( 287 '{"optionalInt32": 0,"repeatedInt32": [],' 288 ' "repeatedNestedMessage": []}' 289 ), 290 ) 291 292 def testProto2_IncludingDefaultValueWithoutPresenceFields(self): 293 message = test_proto2_pb2.TestProto2() 294 self.assertEqual( 295 json.loads( 296 json_format.MessageToJson( 297 message, always_print_fields_with_no_presence=True 298 ) 299 ), 300 json.loads('{"repeatedInt32": [], "repeatedNestedMessage": []}'), 301 ) 302 message.optional_int32 = 0 303 self.assertEqual( 304 json.loads( 305 json_format.MessageToJson( 306 message, always_print_fields_with_no_presence=True 307 ) 308 ), 309 json.loads( 310 '{"optionalInt32": 0,"repeatedInt32": [],' 311 ' "repeatedNestedMessage": []}' 312 ), 313 ) 314 315 def testIntegersRepresentedAsFloat(self): 316 message = json_format_proto3_pb2.TestMessage() 317 json_format.Parse('{"int32Value": -2.147483648e9}', message) 318 self.assertEqual(message.int32_value, -2147483648) 319 json_format.Parse('{"int32Value": 1e5}', message) 320 self.assertEqual(message.int32_value, 100000) 321 json_format.Parse('{"int32Value": 1.0}', message) 322 self.assertEqual(message.int32_value, 1) 323 324 def testMapFields(self): 325 message = json_format_proto3_pb2.TestNestedMap() 326 self.assertEqual( 327 json.loads( 328 json_format.MessageToJson( 329 message, always_print_fields_with_no_presence=True 330 ) 331 ), 332 json.loads( 333 '{' 334 '"boolMap": {},' 335 '"int32Map": {},' 336 '"int64Map": {},' 337 '"uint32Map": {},' 338 '"uint64Map": {},' 339 '"stringMap": {},' 340 '"mapMap": {}' 341 '}' 342 ), 343 ) 344 message.bool_map[True] = 1 345 message.bool_map[False] = 2 346 message.int32_map[1] = 2 347 message.int32_map[2] = 3 348 message.int64_map[1] = 2 349 message.int64_map[2] = 3 350 message.uint32_map[1] = 2 351 message.uint32_map[2] = 3 352 message.uint64_map[1] = 2 353 message.uint64_map[2] = 3 354 message.string_map['1'] = 2 355 message.string_map['null'] = 3 356 message.map_map['1'].bool_map[True] = 3 357 self.assertEqual( 358 json.loads( 359 json_format.MessageToJson( 360 message, always_print_fields_with_no_presence=False 361 ) 362 ), 363 json.loads( 364 '{' 365 '"boolMap": {"false": 2, "true": 1},' 366 '"int32Map": {"1": 2, "2": 3},' 367 '"int64Map": {"1": 2, "2": 3},' 368 '"uint32Map": {"1": 2, "2": 3},' 369 '"uint64Map": {"1": 2, "2": 3},' 370 '"stringMap": {"1": 2, "null": 3},' 371 '"mapMap": {"1": {"boolMap": {"true": 3}}}' 372 '}' 373 ), 374 ) 375 parsed_message = json_format_proto3_pb2.TestNestedMap() 376 self.CheckParseBack(message, parsed_message) 377 378 def testOneofFields(self): 379 message = json_format_proto3_pb2.TestOneof() 380 # Always print does not affect oneof fields. 381 self.assertEqual( 382 json_format.MessageToJson( 383 message, always_print_fields_with_no_presence=True 384 ), 385 '{}', 386 ) 387 message.oneof_int32_value = 0 388 self.assertEqual( 389 json_format.MessageToJson( 390 message, always_print_fields_with_no_presence=True 391 ), 392 '{\n "oneofInt32Value": 0\n}', 393 ) 394 parsed_message = json_format_proto3_pb2.TestOneof() 395 self.CheckParseBack(message, parsed_message) 396 397 def testSurrogates(self): 398 # Test correct surrogate handling. 399 message = json_format_proto3_pb2.TestMessage() 400 json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message) 401 self.assertEqual( 402 message.string_value, b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict') 403 ) 404 405 # Error case: unpaired high surrogate. 406 self.CheckError( 407 '{"stringValue": "\\uD83D"}', 408 r'Invalid \\uXXXX escape|Unpaired.*surrogate', 409 ) 410 411 # Unpaired low surrogate. 412 self.CheckError( 413 '{"stringValue": "\\uDE01"}', 414 r'Invalid \\uXXXX escape|Unpaired.*surrogate', 415 ) 416 417 def testTimestampMessage(self): 418 message = json_format_proto3_pb2.TestTimestamp() 419 message.value.seconds = 0 420 message.value.nanos = 0 421 message.repeated_value.add().seconds = 20 422 message.repeated_value[0].nanos = 1 423 message.repeated_value.add().seconds = 0 424 message.repeated_value[1].nanos = 10000 425 message.repeated_value.add().seconds = 100000000 426 message.repeated_value[2].nanos = 0 427 # Maximum time 428 message.repeated_value.add().seconds = 253402300799 429 message.repeated_value[3].nanos = 999999999 430 # Minimum time 431 message.repeated_value.add().seconds = -62135596800 432 message.repeated_value[4].nanos = 0 433 self.assertEqual( 434 json.loads( 435 json_format.MessageToJson( 436 message, always_print_fields_with_no_presence=True 437 ) 438 ), 439 json.loads( 440 '{' 441 '"value": "1970-01-01T00:00:00Z",' 442 '"repeatedValue": [' 443 ' "1970-01-01T00:00:20.000000001Z",' 444 ' "1970-01-01T00:00:00.000010Z",' 445 ' "1973-03-03T09:46:40Z",' 446 ' "9999-12-31T23:59:59.999999999Z",' 447 ' "0001-01-01T00:00:00Z"' 448 ']' 449 '}' 450 ), 451 ) 452 parsed_message = json_format_proto3_pb2.TestTimestamp() 453 self.CheckParseBack(message, parsed_message) 454 text = ( 455 r'{"value": "1970-01-01T00:00:00.01+08:00",' 456 r'"repeatedValue":[' 457 r' "1970-01-01T00:00:00.01+08:30",' 458 r' "1970-01-01T00:00:00.01-01:23"]}' 459 ) 460 json_format.Parse(text, parsed_message) 461 self.assertEqual(parsed_message.value.seconds, -8 * 3600) 462 self.assertEqual(parsed_message.value.nanos, 10000000) 463 self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600) 464 self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60) 465 466 def testDurationMessage(self): 467 message = json_format_proto3_pb2.TestDuration() 468 message.value.seconds = 1 469 message.repeated_value.add().seconds = 0 470 message.repeated_value[0].nanos = 10 471 message.repeated_value.add().seconds = -1 472 message.repeated_value[1].nanos = -1000 473 message.repeated_value.add().seconds = 10 474 message.repeated_value[2].nanos = 11000000 475 message.repeated_value.add().seconds = -315576000000 476 message.repeated_value.add().seconds = 315576000000 477 self.assertEqual( 478 json.loads( 479 json_format.MessageToJson( 480 message, always_print_fields_with_no_presence=True 481 ) 482 ), 483 json.loads( 484 '{' 485 '"value": "1s",' 486 '"repeatedValue": [' 487 ' "0.000000010s",' 488 ' "-1.000001s",' 489 ' "10.011s",' 490 ' "-315576000000s",' 491 ' "315576000000s"' 492 ']' 493 '}' 494 ), 495 ) 496 parsed_message = json_format_proto3_pb2.TestDuration() 497 self.CheckParseBack(message, parsed_message) 498 499 def testFieldMaskMessage(self): 500 message = json_format_proto3_pb2.TestFieldMask() 501 message.value.paths.append('foo.bar') 502 message.value.paths.append('bar') 503 self.assertEqual( 504 json_format.MessageToJson( 505 message, always_print_fields_with_no_presence=True 506 ), 507 '{\n "value": "foo.bar,bar"\n}', 508 ) 509 parsed_message = json_format_proto3_pb2.TestFieldMask() 510 self.CheckParseBack(message, parsed_message) 511 512 message.value.Clear() 513 self.assertEqual( 514 json_format.MessageToJson( 515 message, always_print_fields_with_no_presence=True 516 ), 517 '{\n "value": ""\n}', 518 ) 519 self.CheckParseBack(message, parsed_message) 520 521 def testWrapperMessage(self): 522 message = json_format_proto3_pb2.TestWrapper() 523 message.bool_value.value = False 524 message.int32_value.value = 0 525 message.string_value.value = '' 526 message.bytes_value.value = b'' 527 message.repeated_bool_value.add().value = True 528 message.repeated_bool_value.add().value = False 529 message.repeated_int32_value.add() 530 self.assertEqual( 531 json.loads( 532 json_format.MessageToJson( 533 message, always_print_fields_with_no_presence=True 534 ) 535 ), 536 json.loads( 537 '{\n' 538 ' "int32Value": 0,' 539 ' "boolValue": false,' 540 ' "stringValue": "",' 541 ' "bytesValue": "",' 542 ' "repeatedBoolValue": [true, false],' 543 ' "repeatedInt32Value": [0],' 544 ' "repeatedUint32Value": [],' 545 ' "repeatedFloatValue": [],' 546 ' "repeatedDoubleValue": [],' 547 ' "repeatedBytesValue": [],' 548 ' "repeatedInt64Value": [],' 549 ' "repeatedUint64Value": [],' 550 ' "repeatedStringValue": []' 551 '}' 552 ), 553 ) 554 parsed_message = json_format_proto3_pb2.TestWrapper() 555 self.CheckParseBack(message, parsed_message) 556 557 def testStructMessage(self): 558 message = json_format_proto3_pb2.TestStruct() 559 message.value['name'] = 'Jim' 560 message.value['age'] = 10 561 message.value['attend'] = True 562 message.value['email'] = None 563 message.value.get_or_create_struct('address')['city'] = 'SFO' 564 message.value['address']['house_number'] = 1024 565 message.value.get_or_create_struct('empty_struct') 566 message.value.get_or_create_list('empty_list') 567 struct_list = message.value.get_or_create_list('list') 568 struct_list.extend([6, 'seven', True, False, None]) 569 struct_list.add_struct()['subkey2'] = 9 570 message.repeated_value.add()['age'] = 11 571 message.repeated_value.add() 572 self.assertEqual( 573 json.loads( 574 json_format.MessageToJson( 575 message, always_print_fields_with_no_presence=False 576 ) 577 ), 578 json.loads( 579 '{' 580 ' "value": {' 581 ' "address": {' 582 ' "city": "SFO", ' 583 ' "house_number": 1024' 584 ' }, ' 585 ' "empty_struct": {}, ' 586 ' "empty_list": [], ' 587 ' "age": 10, ' 588 ' "name": "Jim", ' 589 ' "attend": true, ' 590 ' "email": null, ' 591 ' "list": [6, "seven", true, false, null, {"subkey2": 9}]' 592 ' },' 593 ' "repeatedValue": [{"age": 11}, {}]' 594 '}' 595 ), 596 ) 597 parsed_message = json_format_proto3_pb2.TestStruct() 598 self.CheckParseBack(message, parsed_message) 599 # check for regression; this used to raise 600 parsed_message.value['empty_struct'] 601 parsed_message.value['empty_list'] 602 603 def testValueMessage(self): 604 message = json_format_proto3_pb2.TestValue() 605 message.value.string_value = 'hello' 606 message.repeated_value.add().number_value = 11.1 607 message.repeated_value.add().bool_value = False 608 message.repeated_value.add().null_value = 0 609 self.assertEqual( 610 json.loads( 611 json_format.MessageToJson( 612 message, always_print_fields_with_no_presence=False 613 ) 614 ), 615 json.loads( 616 '{ "value": "hello", "repeatedValue": [11.1, false, null]}' 617 ), 618 ) 619 parsed_message = json_format_proto3_pb2.TestValue() 620 self.CheckParseBack(message, parsed_message) 621 # Can't parse back if the Value message is not set. 622 message.repeated_value.add() 623 self.assertEqual( 624 json.loads( 625 json_format.MessageToJson( 626 message, always_print_fields_with_no_presence=False 627 ) 628 ), 629 json.loads( 630 '{ "value": "hello", "repeatedValue": [11.1, false, null, null]}' 631 ), 632 ) 633 message.Clear() 634 json_format.Parse('{"value": null}', message) 635 self.assertEqual(message.value.WhichOneof('kind'), 'null_value') 636 637 def testValueMessageErrors(self): 638 message = json_format_proto3_pb2.TestValue() 639 message.value.number_value = math.inf 640 with self.assertRaises(json_format.SerializeToJsonError) as cm: 641 json_format.MessageToJson(message) 642 self.assertEqual( 643 'Failed to serialize value field: Fail to serialize Infinity for ' 644 'Value.number_value, which would parse as string_value.', 645 str(cm.exception), 646 ) 647 message.value.number_value = math.nan 648 with self.assertRaises(json_format.SerializeToJsonError) as cm: 649 json_format.MessageToJson(message) 650 self.assertEqual( 651 'Failed to serialize value field: Fail to serialize NaN for ' 652 'Value.number_value, which would parse as string_value.', 653 str(cm.exception), 654 ) 655 656 def testListValueMessage(self): 657 message = json_format_proto3_pb2.TestListValue() 658 message.value.values.add().number_value = 11.1 659 message.value.values.add().null_value = 0 660 message.value.values.add().bool_value = True 661 message.value.values.add().string_value = 'hello' 662 message.value.values.add().struct_value['name'] = 'Jim' 663 message.repeated_value.add().values.add().number_value = 1 664 message.repeated_value.add() 665 self.assertEqual( 666 json.loads( 667 json_format.MessageToJson( 668 message, always_print_fields_with_no_presence=False 669 ) 670 ), 671 json.loads( 672 '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,' 673 '"repeatedValue": [[1], []]}' 674 ), 675 ) 676 parsed_message = json_format_proto3_pb2.TestListValue() 677 self.CheckParseBack(message, parsed_message) 678 679 def testNullValue(self): 680 message = json_format_proto3_pb2.TestOneof() 681 message.oneof_null_value = 0 682 self.assertEqual( 683 json_format.MessageToJson(message), '{\n "oneofNullValue": null\n}' 684 ) 685 parsed_message = json_format_proto3_pb2.TestOneof() 686 self.CheckParseBack(message, parsed_message) 687 # Check old format is also accepted 688 new_message = json_format_proto3_pb2.TestOneof() 689 json_format.Parse('{\n "oneofNullValue": "NULL_VALUE"\n}', new_message) 690 self.assertEqual( 691 json_format.MessageToJson(new_message), '{\n "oneofNullValue": null\n}' 692 ) 693 694 def testAnyMessage(self): 695 message = json_format_proto3_pb2.TestAny() 696 value1 = json_format_proto3_pb2.MessageType() 697 value2 = json_format_proto3_pb2.MessageType() 698 value1.value = 1234 699 value2.value = 5678 700 message.value.Pack(value1) 701 message.repeated_value.add().Pack(value1) 702 message.repeated_value.add().Pack(value2) 703 message.repeated_value.add() 704 self.assertEqual( 705 json.loads( 706 json_format.MessageToJson( 707 message, always_print_fields_with_no_presence=True 708 ) 709 ), 710 json.loads( 711 '{\n' 712 ' "repeatedValue": [ {\n' 713 ' "@type": "type.googleapis.com/proto3.MessageType",\n' 714 ' "value": 1234\n' 715 ' }, {\n' 716 ' "@type": "type.googleapis.com/proto3.MessageType",\n' 717 ' "value": 5678\n' 718 ' },\n' 719 ' {}],\n' 720 ' "value": {\n' 721 ' "@type": "type.googleapis.com/proto3.MessageType",\n' 722 ' "value": 1234\n' 723 ' }\n' 724 '}\n' 725 ), 726 ) 727 parsed_message = json_format_proto3_pb2.TestAny() 728 self.CheckParseBack(message, parsed_message) 729 # Must print @type first 730 test_message = json_format_proto3_pb2.TestMessage( 731 bool_value=True, 732 int32_value=20, 733 int64_value=-20, 734 uint32_value=20, 735 uint64_value=20, 736 double_value=3.14, 737 string_value='foo', 738 ) 739 message.Clear() 740 message.value.Pack(test_message) 741 self.assertEqual( 742 json_format.MessageToJson( 743 message, always_print_fields_with_no_presence=False 744 )[0:68], 745 '{\n' 746 ' "value": {\n' 747 ' "@type": "type.googleapis.com/proto3.TestMessage"', 748 ) 749 750 def testAnyMessageDescriptorPoolMissingType(self): 751 packed_message = unittest_pb2.OneString() 752 packed_message.data = 'string' 753 message = any_test_pb2.TestAny() 754 message.any_value.Pack(packed_message) 755 empty_pool = descriptor_pool.DescriptorPool() 756 with self.assertRaises(TypeError) as cm: 757 json_format.MessageToJson( 758 message, 759 always_print_fields_with_no_presence=True, 760 descriptor_pool=empty_pool, 761 ) 762 self.assertEqual( 763 'Can not find message descriptor by type_url:' 764 ' type.googleapis.com/protobuf_unittest.OneString', 765 str(cm.exception), 766 ) 767 768 def testWellKnownInAnyMessage(self): 769 message = any_pb2.Any() 770 int32_value = wrappers_pb2.Int32Value() 771 int32_value.value = 1234 772 message.Pack(int32_value) 773 self.assertEqual( 774 json.loads( 775 json_format.MessageToJson( 776 message, always_print_fields_with_no_presence=True 777 ) 778 ), 779 json.loads( 780 '{\n' 781 ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n' 782 ' "value": 1234\n' 783 '}\n' 784 ), 785 ) 786 parsed_message = any_pb2.Any() 787 self.CheckParseBack(message, parsed_message) 788 789 timestamp = timestamp_pb2.Timestamp() 790 message.Pack(timestamp) 791 self.assertEqual( 792 json.loads( 793 json_format.MessageToJson( 794 message, always_print_fields_with_no_presence=True 795 ) 796 ), 797 json.loads( 798 '{\n' 799 ' "@type": "type.googleapis.com/google.protobuf.Timestamp",\n' 800 ' "value": "1970-01-01T00:00:00Z"\n' 801 '}\n' 802 ), 803 ) 804 self.CheckParseBack(message, parsed_message) 805 806 duration = duration_pb2.Duration() 807 duration.seconds = 1 808 message.Pack(duration) 809 self.assertEqual( 810 json.loads( 811 json_format.MessageToJson( 812 message, always_print_fields_with_no_presence=True 813 ) 814 ), 815 json.loads( 816 '{\n' 817 ' "@type": "type.googleapis.com/google.protobuf.Duration",\n' 818 ' "value": "1s"\n' 819 '}\n' 820 ), 821 ) 822 self.CheckParseBack(message, parsed_message) 823 824 field_mask = field_mask_pb2.FieldMask() 825 field_mask.paths.append('foo.bar') 826 field_mask.paths.append('bar') 827 message.Pack(field_mask) 828 self.assertEqual( 829 json.loads( 830 json_format.MessageToJson( 831 message, always_print_fields_with_no_presence=True 832 ) 833 ), 834 json.loads( 835 '{\n' 836 ' "@type": "type.googleapis.com/google.protobuf.FieldMask",\n' 837 ' "value": "foo.bar,bar"\n' 838 '}\n' 839 ), 840 ) 841 self.CheckParseBack(message, parsed_message) 842 843 struct_message = struct_pb2.Struct() 844 struct_message['name'] = 'Jim' 845 message.Pack(struct_message) 846 self.assertEqual( 847 json.loads( 848 json_format.MessageToJson( 849 message, always_print_fields_with_no_presence=True 850 ) 851 ), 852 json.loads( 853 '{\n' 854 ' "@type": "type.googleapis.com/google.protobuf.Struct",\n' 855 ' "value": {"name": "Jim"}\n' 856 '}\n' 857 ), 858 ) 859 self.CheckParseBack(message, parsed_message) 860 861 nested_any = any_pb2.Any() 862 int32_value.value = 5678 863 nested_any.Pack(int32_value) 864 message.Pack(nested_any) 865 self.assertEqual( 866 json.loads( 867 json_format.MessageToJson( 868 message, always_print_fields_with_no_presence=True 869 ) 870 ), 871 json.loads( 872 '{\n' 873 ' "@type": "type.googleapis.com/google.protobuf.Any",\n' 874 ' "value": {\n' 875 ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n' 876 ' "value": 5678\n' 877 ' }\n' 878 '}\n' 879 ), 880 ) 881 self.CheckParseBack(message, parsed_message) 882 883 def testParseNull(self): 884 message = json_format_proto3_pb2.TestMessage() 885 parsed_message = json_format_proto3_pb2.TestMessage() 886 self.FillAllFields(parsed_message) 887 json_format.Parse( 888 '{"int32Value": null, ' 889 '"int64Value": null, ' 890 '"uint32Value": null,' 891 '"uint64Value": null,' 892 '"floatValue": null,' 893 '"doubleValue": null,' 894 '"boolValue": null,' 895 '"stringValue": null,' 896 '"bytesValue": null,' 897 '"messageValue": null,' 898 '"enumValue": null,' 899 '"repeatedInt32Value": null,' 900 '"repeatedInt64Value": null,' 901 '"repeatedUint32Value": null,' 902 '"repeatedUint64Value": null,' 903 '"repeatedFloatValue": null,' 904 '"repeatedDoubleValue": null,' 905 '"repeatedBoolValue": null,' 906 '"repeatedStringValue": null,' 907 '"repeatedBytesValue": null,' 908 '"repeatedMessageValue": null,' 909 '"repeatedEnumValue": null' 910 '}', 911 parsed_message, 912 ) 913 self.assertEqual(message, parsed_message) 914 # Null and {} should have different behavior for sub message. 915 self.assertFalse(parsed_message.HasField('message_value')) 916 json_format.Parse('{"messageValue": {}}', parsed_message) 917 self.assertTrue(parsed_message.HasField('message_value')) 918 # Null is not allowed to be used as an element in repeated field. 919 self.assertRaisesRegex( 920 json_format.ParseError, 921 r'Failed to parse repeatedInt32Value field: ' 922 r'null is not allowed to be used as an element in a repeated field ' 923 r'at TestMessage.repeatedInt32Value\[1\].', 924 json_format.Parse, 925 '{"repeatedInt32Value":[1, null]}', 926 parsed_message, 927 ) 928 self.CheckError( 929 '{"repeatedMessageValue":[null]}', 930 r'Failed to parse repeatedMessageValue field: null is not' 931 r' allowed to be used as an element in a repeated field ' 932 r'at TestMessage.repeatedMessageValue\[0\].', 933 ) 934 935 def testNanFloat(self): 936 message = json_format_proto3_pb2.TestMessage() 937 message.float_value = float('nan') 938 text = '{\n "floatValue": "NaN"\n}' 939 self.assertEqual(json_format.MessageToJson(message), text) 940 parsed_message = json_format_proto3_pb2.TestMessage() 941 json_format.Parse(text, parsed_message) 942 self.assertTrue(math.isnan(parsed_message.float_value)) 943 944 def testParseDoubleToFloat(self): 945 message = json_format_proto3_pb2.TestMessage() 946 text = '{"repeatedDoubleValue": [3.4028235e+39, 1.4028235e-39]\n}' 947 json_format.Parse(text, message) 948 self.assertEqual(message.repeated_double_value[0], 3.4028235e39) 949 self.assertEqual(message.repeated_double_value[1], 1.4028235e-39) 950 text = '{"repeatedFloatValue": [3.4028235e+39, 1.4028235e-39]\n}' 951 self.CheckError( 952 text, 953 r'Failed to parse repeatedFloatValue field: ' 954 r'Float value too large at TestMessage.repeatedFloatValue\[0\].', 955 ) 956 957 def testFloatPrecision(self): 958 message = json_format_proto3_pb2.TestMessage() 959 message.float_value = 1.123456789 960 # Set to 8 valid digits. 961 text = '{\n "floatValue": 1.1234568\n}' 962 self.assertEqual( 963 json_format.MessageToJson(message, float_precision=8), text 964 ) 965 # Set to 7 valid digits. 966 text = '{\n "floatValue": 1.123457\n}' 967 self.assertEqual( 968 json_format.MessageToJson(message, float_precision=7), text 969 ) 970 971 # Default float_precision will automatic print shortest float. 972 message.float_value = 1.1000000011 973 text = '{\n "floatValue": 1.1\n}' 974 self.assertEqual(json_format.MessageToJson(message), text) 975 message.float_value = 1.00000075e-36 976 text = '{\n "floatValue": 1.00000075e-36\n}' 977 self.assertEqual(json_format.MessageToJson(message), text) 978 message.float_value = 12345678912345e11 979 text = '{\n "floatValue": 1.234568e+24\n}' 980 self.assertEqual(json_format.MessageToJson(message), text) 981 982 # Test a bunch of data and check json encode/decode do not 983 # lose precision 984 value_list = [0x00, 0xD8, 0x6E, 0x00] 985 msg2 = json_format_proto3_pb2.TestMessage() 986 for a in range(0, 256): 987 value_list[3] = a 988 for b in range(0, 256): 989 value_list[0] = b 990 byte_array = bytearray(value_list) 991 message.float_value = struct.unpack('<f', byte_array)[0] 992 self.CheckParseBack(message, msg2) 993 994 def testParseEmptyText(self): 995 self.CheckError('', r'Failed to load JSON: (Expecting value)|(No JSON).') 996 997 def testParseEnumValue(self): 998 message = json_format_proto3_pb2.TestMessage() 999 text = '{"enumValue": 0}' 1000 json_format.Parse(text, message) 1001 text = '{"enumValue": 1}' 1002 json_format.Parse(text, message) 1003 self.CheckError( 1004 '{"enumValue": "baz"}', 1005 'Failed to parse enumValue field: Invalid enum value baz ' 1006 'for enum type proto3.EnumType at TestMessage.enumValue.', 1007 ) 1008 # Proto3 accepts numeric unknown enums. 1009 text = '{"enumValue": 12345}' 1010 json_format.Parse(text, message) 1011 # Proto2 does not accept numeric unknown enums. 1012 message = unittest_pb2.TestAllTypes() 1013 self.assertRaisesRegex( 1014 json_format.ParseError, 1015 'Failed to parse optionalNestedEnum field: Invalid enum value 12345 ' 1016 'for enum type protobuf_unittest.TestAllTypes.NestedEnum at ' 1017 'TestAllTypes.optionalNestedEnum.', 1018 json_format.Parse, 1019 '{"optionalNestedEnum": 12345}', 1020 message, 1021 ) 1022 1023 def testParseUnknownEnumStringValue_Scalar_Proto2(self): 1024 message = json_format_pb2.TestNumbers() 1025 text = '{"a": "UNKNOWN_STRING_VALUE"}' 1026 json_format.Parse(text, message, ignore_unknown_fields=True) 1027 1028 self.assertFalse(message.HasField('a')) 1029 1030 def testParseErrorForUnknownEnumValue_ScalarWithoutIgnore_Proto2(self): 1031 message = json_format_pb2.TestNumbers() 1032 self.assertRaisesRegex( 1033 json_format.ParseError, 1034 'Invalid enum value', 1035 json_format.Parse, '{"a": "UNKNOWN_STRING_VALUE"}', message) 1036 1037 def testParseUnknownEnumStringValue_Repeated_Proto2(self): 1038 message = json_format_pb2.TestRepeatedEnum() 1039 text = '{"repeatedEnum": ["UNKNOWN_STRING_VALUE", "BUFFER"]}' 1040 json_format.Parse(text, message, ignore_unknown_fields=True) 1041 1042 self.assertEqual(len(message.repeated_enum), 1) 1043 self.assertTrue(message.repeated_enum[0] == json_format_pb2.BUFFER) 1044 1045 def testParseUnknownEnumStringValue_Map_Proto2(self): 1046 message = json_format_pb2.TestMapOfEnums() 1047 text = '{"enumMap": {"key1": "BUFFER", "key2": "UNKNOWN_STRING_VALUE"}}' 1048 json_format.Parse(text, message, ignore_unknown_fields=True) 1049 1050 self.assertTrue(message.enum_map['key1'] == json_format_pb2.BUFFER) 1051 self.assertFalse('key2' in message.enum_map) 1052 1053 def testParseUnknownEnumStringValue_ExtensionField_Proto2(self): 1054 message = json_format_pb2.TestMessageWithExtension() 1055 text = """ 1056 {"[protobuf_unittest.TestExtension.enum_ext]": "UNKNOWN_STRING_VALUE"} 1057 """ 1058 json_format.Parse(text, message, ignore_unknown_fields=True) 1059 1060 self.assertFalse(json_format_pb2.TestExtension.enum_ext in 1061 message.Extensions) 1062 1063 def testParseUnknownEnumStringValue_ExtensionFieldWithoutIgnore_Proto2(self): 1064 message = json_format_pb2.TestMessageWithExtension() 1065 text = """ 1066 {"[protobuf_unittest.TestExtension.enum_ext]": "UNKNOWN_STRING_VALUE"} 1067 """ 1068 self.assertRaisesRegex( 1069 json_format.ParseError, 1070 'Invalid enum value', 1071 json_format.Parse, text, message) 1072 1073 def testParseUnknownEnumStringValue_Scalar_Proto3(self): 1074 message = json_format_proto3_pb2.TestMessage() 1075 text = '{"enumValue": "UNKNOWN_STRING_VALUE"}' 1076 1077 json_format.Parse(text, message, ignore_unknown_fields=True) 1078 self.assertEqual(message.enum_value, 0) 1079 1080 def testParseUnknownEnumStringValue_Repeated_Proto3(self): 1081 message = json_format_proto3_pb2.TestMessage() 1082 text = '{"repeatedEnumValue": ["UNKNOWN_STRING_VALUE", "FOO"]}' 1083 json_format.Parse(text, message, ignore_unknown_fields=True) 1084 1085 self.assertEqual(len(message.repeated_enum_value), 1) 1086 self.assertTrue(message.repeated_enum_value[0] == 1087 json_format_proto3_pb2.FOO) 1088 1089 def testParseUnknownEnumStringValue_Map_Proto3(self): 1090 message = json_format_proto3_pb2.MapOfEnums() 1091 text = '{"map": {"key1": "FOO", "key2": "UNKNOWN_STRING_VALUE"}}' 1092 json_format.Parse(text, message, ignore_unknown_fields=True) 1093 1094 self.assertTrue(message.map['key1'] == json_format_proto3_pb2.FOO) 1095 self.assertFalse('key2' in message.map) 1096 1097 def testBytes(self): 1098 message = json_format_proto3_pb2.TestMessage() 1099 # Test url base64 1100 text = '{"bytesValue": "-_"}' 1101 json_format.Parse(text, message) 1102 self.assertEqual(message.bytes_value, b'\xfb') 1103 # Test padding 1104 text = '{"bytesValue": "AQI="}' 1105 json_format.Parse(text, message) 1106 self.assertEqual(message.bytes_value, b'\x01\x02') 1107 text = '{"bytesValue": "AQI"}' 1108 json_format.Parse(text, message) 1109 self.assertEqual(message.bytes_value, b'\x01\x02') 1110 text = '{"bytesValue": "AQI*"}' 1111 json_format.Parse(text, message) 1112 self.assertEqual(message.bytes_value, b'\x01\x02') 1113 1114 def testParseBadIdentifier(self): 1115 self.CheckError( 1116 '{int32Value: 1}', 1117 ( 1118 r'Failed to load JSON: Expecting property name' 1119 r'( enclosed in double quotes)?: line 1' 1120 ), 1121 ) 1122 self.CheckError( 1123 '{"unknownName": 1}', 1124 'Message type "proto3.TestMessage" has no field named ' 1125 '"unknownName" at "TestMessage".', 1126 ) 1127 1128 def testIgnoreUnknownField(self): 1129 text = '{"unknownName": 1}' 1130 parsed_message = json_format_proto3_pb2.TestMessage() 1131 json_format.Parse(text, parsed_message, ignore_unknown_fields=True) 1132 text = ( 1133 '{\n' 1134 ' "repeatedValue": [ {\n' 1135 ' "@type": "type.googleapis.com/proto3.MessageType",\n' 1136 ' "unknownName": 1\n' 1137 ' }]\n' 1138 '}\n' 1139 ) 1140 parsed_message = json_format_proto3_pb2.TestAny() 1141 json_format.Parse(text, parsed_message, ignore_unknown_fields=True) 1142 1143 def testDuplicateField(self): 1144 self.CheckError( 1145 '{"int32Value": 1,\n"int32Value":2}', 1146 'Failed to load JSON: duplicate key int32Value.', 1147 ) 1148 1149 def testInvalidBoolValue(self): 1150 self.CheckError( 1151 '{"boolValue": 1}', 1152 'Failed to parse boolValue field: ' 1153 'Expected true or false without quotes at TestMessage.boolValue.', 1154 ) 1155 self.CheckError( 1156 '{"boolValue": "true"}', 1157 'Failed to parse boolValue field: ' 1158 'Expected true or false without quotes at TestMessage.boolValue.', 1159 ) 1160 1161 def testInvalidIntegerValue(self): 1162 message = json_format_proto3_pb2.TestMessage() 1163 text = '{"int32Value": 0x12345}' 1164 self.assertRaises(json_format.ParseError, json_format.Parse, text, message) 1165 self.CheckError( 1166 '{"int32Value": 1.5}', 1167 'Failed to parse int32Value field: ' 1168 "Couldn't parse integer: 1.5 at TestMessage.int32Value.", 1169 ) 1170 self.CheckError( 1171 '{"int32Value": 012345}', 1172 (r'Failed to load JSON: Expecting \'?,\'? delimiter: ' r'line 1.'), 1173 ) 1174 self.CheckError( 1175 '{"int32Value": " 1 "}', 1176 'Failed to parse int32Value field: ' 1177 'Couldn\'t parse integer: " 1 " at TestMessage.int32Value.', 1178 ) 1179 self.CheckError( 1180 '{"int32Value": "1 "}', 1181 'Failed to parse int32Value field: ' 1182 'Couldn\'t parse integer: "1 " at TestMessage.int32Value.', 1183 ) 1184 self.CheckError( 1185 '{"int32Value": false}', 1186 'Failed to parse int32Value field: Bool value False ' 1187 'is not acceptable for integer field at TestMessage.int32Value.', 1188 ) 1189 self.CheckError( 1190 '{"int32Value": 12345678901234567890}', 1191 'Failed to parse int32Value field: Value out of range: ' 1192 '12345678901234567890.', 1193 ) 1194 self.CheckError( 1195 '{"uint32Value": -1}', 1196 'Failed to parse uint32Value field: Value out of range: -1.', 1197 ) 1198 1199 def testInvalidFloatValue(self): 1200 self.CheckError( 1201 '{"floatValue": "nan"}', 1202 "Failed to parse floatValue field: Couldn't " 1203 'parse float "nan", use "NaN" instead at TestMessage.floatValue.', 1204 ) 1205 self.CheckError( 1206 '{"floatValue": NaN}', 1207 "Failed to parse floatValue field: Couldn't " 1208 'parse NaN, use quoted "NaN" instead.', 1209 ) 1210 self.CheckError( 1211 '{"floatValue": Infinity}', 1212 "Failed to parse floatValue field: Couldn't parse Infinity" 1213 ' or value too large, use quoted "Infinity" instead.', 1214 ) 1215 self.CheckError( 1216 '{"floatValue": -Infinity}', 1217 "Failed to parse floatValue field: Couldn't parse " 1218 '-Infinity or value too small, ' 1219 'use quoted "-Infinity" instead.', 1220 ) 1221 self.CheckError( 1222 '{"doubleValue": -1.89769e+308}', 1223 "Failed to parse doubleValue field: Couldn't parse " 1224 '-Infinity or value too small, ' 1225 'use quoted "-Infinity" instead.', 1226 ) 1227 self.CheckError( 1228 '{"floatValue": 3.4028235e+39}', 1229 'Failed to parse floatValue field: Float value too large.', 1230 ) 1231 self.CheckError( 1232 '{"floatValue": -3.502823e+38}', 1233 'Failed to parse floatValue field: Float value too small.', 1234 ) 1235 1236 def testInvalidRepeated(self): 1237 self.CheckError( 1238 '{"repeatedInt32Value": 12345}', 1239 ( 1240 r'Failed to parse repeatedInt32Value field: repeated field' 1241 r' repeatedInt32Value must be in \[\] which is 12345 at' 1242 r' TestMessage.' 1243 ), 1244 ) 1245 1246 def testInvalidMap(self): 1247 message = json_format_proto3_pb2.TestMap() 1248 text = '{"int32Map": {"null": 2, "2": 3}}' 1249 self.assertRaisesRegex( 1250 json_format.ParseError, 1251 'Failed to parse int32Map field: invalid literal', 1252 json_format.Parse, 1253 text, 1254 message, 1255 ) 1256 text = '{"int32Map": {1: 2, "2": 3}}' 1257 self.assertRaisesRegex( 1258 json_format.ParseError, 1259 ( 1260 r'Failed to load JSON: Expecting property name' 1261 r'( enclosed in double quotes)?: line 1' 1262 ), 1263 json_format.Parse, 1264 text, 1265 message, 1266 ) 1267 text = '{"boolMap": {"null": 1}}' 1268 self.assertRaisesRegex( 1269 json_format.ParseError, 1270 'Failed to parse boolMap field: Expected "true" or "false", not null at' 1271 ' TestMap.boolMap.key', 1272 json_format.Parse, 1273 text, 1274 message, 1275 ) 1276 text = r'{"stringMap": {"a": 3, "\u0061": 2}}' 1277 self.assertRaisesRegex( 1278 json_format.ParseError, 1279 'Failed to load JSON: duplicate key a', 1280 json_format.Parse, 1281 text, 1282 message, 1283 ) 1284 text = r'{"stringMap": 0}' 1285 self.assertRaisesRegex( 1286 json_format.ParseError, 1287 'Failed to parse stringMap field: Map field string_map must be ' 1288 'in a dict which is 0 at TestMap.stringMap.', 1289 json_format.Parse, 1290 text, 1291 message, 1292 ) 1293 1294 def testInvalidTimestamp(self): 1295 message = json_format_proto3_pb2.TestTimestamp() 1296 text = '{"value": "10000-01-01T00:00:00.00Z"}' 1297 self.assertRaisesRegex( 1298 json_format.ParseError, 1299 'Failed to parse value field: ' 1300 "time data '10000-01-01T00:00:00' does not match" 1301 " format '%Y-%m-%dT%H:%M:%S' at TestTimestamp.value.", 1302 json_format.Parse, 1303 text, 1304 message, 1305 ) 1306 text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}' 1307 self.assertRaisesRegex( 1308 json_format.ParseError, 1309 'nanos 0123456789012 more than 9 fractional digits.', 1310 json_format.Parse, 1311 text, 1312 message, 1313 ) 1314 text = '{"value": "1972-01-01T01:00:00.01+08"}' 1315 self.assertRaisesRegex( 1316 json_format.ParseError, 1317 r'Invalid timezone offset value: \+08.', 1318 json_format.Parse, 1319 text, 1320 message, 1321 ) 1322 # Time smaller than minimum time. 1323 text = '{"value": "0000-01-01T00:00:00Z"}' 1324 self.assertRaisesRegex( 1325 json_format.ParseError, 1326 'Failed to parse value field: year (0 )?is out of range.', 1327 json_format.Parse, 1328 text, 1329 message, 1330 ) 1331 # Time bigger than maximum time. 1332 message.value.seconds = 253402300800 1333 self.assertRaisesRegex(json_format.SerializeToJsonError, 1334 'Timestamp is not valid', 1335 json_format.MessageToJson, message) 1336 # Nanos smaller than 0 1337 message.value.seconds = 0 1338 message.value.nanos = -1 1339 self.assertRaisesRegex( 1340 json_format.SerializeToJsonError, 1341 'Timestamp is not valid', 1342 json_format.MessageToJson, 1343 message, 1344 ) 1345 # Lower case t does not accept. 1346 text = '{"value": "0001-01-01t00:00:00Z"}' 1347 with self.assertRaises(json_format.ParseError) as e: 1348 json_format.Parse(text, message) 1349 self.assertEqual( 1350 'Failed to parse value field: ' 1351 "time data '0001-01-01t00:00:00' does not match format " 1352 "'%Y-%m-%dT%H:%M:%S', lowercase 't' is not accepted " 1353 'at TestTimestamp.value.', 1354 str(e.exception), 1355 ) 1356 1357 def testInvalidOneof(self): 1358 message = json_format_proto3_pb2.TestOneof() 1359 text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}' 1360 self.assertRaisesRegex( 1361 json_format.ParseError, 1362 'Message type "proto3.TestOneof"' 1363 ' should not have multiple "oneof_value" oneof fields at "TestOneof".', 1364 json_format.Parse, 1365 text, 1366 message, 1367 ) 1368 1369 def testInvalidListValue(self): 1370 message = json_format_proto3_pb2.TestListValue() 1371 text = '{"value": 1234}' 1372 self.assertRaisesRegex( 1373 json_format.ParseError, 1374 r'Failed to parse value field: ListValue must be in \[\] which is ' 1375 '1234 at TestListValue.value.', 1376 json_format.Parse, 1377 text, 1378 message, 1379 ) 1380 1381 class UnknownClass(object): 1382 1383 def __str__(self): 1384 return 'v' 1385 1386 self.assertRaisesRegex( 1387 json_format.ParseError, 1388 r' at TestListValue.value\[1\].fake.', 1389 json_format.ParseDict, 1390 {'value': ['hello', {'fake': UnknownClass()}]}, 1391 message, 1392 ) 1393 1394 def testInvalidStruct(self): 1395 message = json_format_proto3_pb2.TestStruct() 1396 text = '{"value": 1234}' 1397 self.assertRaisesRegex( 1398 json_format.ParseError, 1399 'Failed to parse value field: Struct must be in a dict which is ' 1400 '1234 at TestStruct.value', 1401 json_format.Parse, 1402 text, 1403 message, 1404 ) 1405 1406 def testTimestampInvalidStringValue(self): 1407 message = json_format_proto3_pb2.TestTimestamp() 1408 text = '{"value": {"foo": 123}}' 1409 self.assertRaisesRegex( 1410 json_format.ParseError, 1411 r"Timestamp JSON value not a string: {u?'foo': 123}", 1412 json_format.Parse, 1413 text, 1414 message, 1415 ) 1416 1417 def testDurationInvalidStringValue(self): 1418 message = json_format_proto3_pb2.TestDuration() 1419 text = '{"value": {"foo": 123}}' 1420 self.assertRaisesRegex( 1421 json_format.ParseError, 1422 r"Duration JSON value not a string: {u?'foo': 123}", 1423 json_format.Parse, 1424 text, 1425 message, 1426 ) 1427 1428 def testFieldMaskInvalidStringValue(self): 1429 message = json_format_proto3_pb2.TestFieldMask() 1430 text = '{"value": {"foo": 123}}' 1431 self.assertRaisesRegex( 1432 json_format.ParseError, 1433 r"FieldMask JSON value not a string: {u?'foo': 123}", 1434 json_format.Parse, 1435 text, 1436 message, 1437 ) 1438 1439 def testInvalidAny(self): 1440 message = any_pb2.Any() 1441 text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}' 1442 self.assertRaisesRegex(json_format.ParseError, 'KeyError: \'value\'', json_format.Parse, text, message) 1443 text = '{"value": 1234}' 1444 self.assertRaisesRegex( 1445 json_format.ParseError, 1446 '@type is missing when parsing any message at Any', 1447 json_format.Parse, 1448 text, 1449 message, 1450 ) 1451 text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}' 1452 self.assertRaisesRegex( 1453 json_format.ParseError, 1454 'Can not find message descriptor by type_url: ' 1455 'type.googleapis.com/MessageNotExist at Any', 1456 json_format.Parse, 1457 text, 1458 message, 1459 ) 1460 # Only last part is to be used: b/25630112 1461 text = ( 1462 r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",' 1463 r'"value": 1234}' 1464 ) 1465 json_format.Parse(text, message) 1466 1467 def testPreservingProtoFieldNames(self): 1468 message = json_format_proto3_pb2.TestMessage() 1469 message.int32_value = 12345 1470 self.assertEqual( 1471 '{\n "int32Value": 12345\n}', json_format.MessageToJson(message) 1472 ) 1473 self.assertEqual( 1474 '{\n "int32_value": 12345\n}', 1475 json_format.MessageToJson( 1476 message, 1477 always_print_fields_with_no_presence=False, 1478 preserving_proto_field_name=True, 1479 ), 1480 ) 1481 # When always_print_fields_with_no_presence is True. 1482 message = json_format_proto3_pb2.TestTimestamp() 1483 self.assertEqual( 1484 '{\n "repeatedValue": []\n}', 1485 json_format.MessageToJson( 1486 message, 1487 always_print_fields_with_no_presence=True, 1488 ), 1489 ) 1490 self.assertEqual( 1491 '{\n "repeated_value": []\n}', 1492 json_format.MessageToJson( 1493 message, 1494 always_print_fields_with_no_presence=True, 1495 preserving_proto_field_name=True, 1496 ), 1497 ) 1498 1499 # Parsers accept both original proto field names and lowerCamelCase names. 1500 message = json_format_proto3_pb2.TestMessage() 1501 json_format.Parse('{"int32Value": 54321}', message) 1502 self.assertEqual(54321, message.int32_value) 1503 json_format.Parse('{"int32_value": 12345}', message) 1504 self.assertEqual(12345, message.int32_value) 1505 1506 def testIndent(self): 1507 message = json_format_proto3_pb2.TestMessage() 1508 message.int32_value = 12345 1509 self.assertEqual( 1510 '{\n"int32Value": 12345\n}', 1511 json_format.MessageToJson(message, indent=0), 1512 ) 1513 1514 def testFormatEnumsAsInts(self): 1515 message = json_format_proto3_pb2.TestMessage() 1516 message.enum_value = json_format_proto3_pb2.BAR 1517 message.repeated_enum_value.append(json_format_proto3_pb2.FOO) 1518 message.repeated_enum_value.append(json_format_proto3_pb2.BAR) 1519 self.assertEqual( 1520 json.loads('{\n "enumValue": 1,\n "repeatedEnumValue": [0, 1]\n}\n'), 1521 json.loads( 1522 json_format.MessageToJson(message, use_integers_for_enums=True) 1523 ), 1524 ) 1525 1526 def testParseDict(self): 1527 expected = 12345 1528 js_dict = {'int32Value': expected} 1529 message = json_format_proto3_pb2.TestMessage() 1530 json_format.ParseDict(js_dict, message) 1531 self.assertEqual(expected, message.int32_value) 1532 1533 def testParseDictAnyDescriptorPoolMissingType(self): 1534 # Confirm that ParseDict does not raise ParseError with default pool 1535 js_dict = { 1536 'any_value': { 1537 '@type': 'type.googleapis.com/proto3.MessageType', 1538 'value': 1234, 1539 } 1540 } 1541 json_format.ParseDict(js_dict, any_test_pb2.TestAny()) 1542 # Check ParseDict raises ParseError with empty pool 1543 js_dict = { 1544 'any_value': { 1545 '@type': 'type.googleapis.com/proto3.MessageType', 1546 'value': 1234, 1547 } 1548 } 1549 with self.assertRaises(json_format.ParseError) as cm: 1550 empty_pool = descriptor_pool.DescriptorPool() 1551 json_format.ParseDict( 1552 js_dict, any_test_pb2.TestAny(), descriptor_pool=empty_pool 1553 ) 1554 self.assertEqual( 1555 str(cm.exception), 1556 'Failed to parse any_value field: Can not find message descriptor by' 1557 ' type_url: type.googleapis.com/proto3.MessageType at ' 1558 'TestAny.any_value.', 1559 ) 1560 1561 def testParseDictUnknownValueType(self): 1562 class UnknownClass(object): 1563 1564 def __repr__(self): 1565 return 'v' 1566 1567 message = json_format_proto3_pb2.TestValue() 1568 self.assertRaisesRegex( 1569 json_format.ParseError, 1570 r"Value v has unexpected type <class '.*\.UnknownClass'>.", 1571 json_format.ParseDict, 1572 {'value': UnknownClass()}, 1573 message, 1574 ) 1575 1576 def testMessageToDict(self): 1577 message = json_format_proto3_pb2.TestMessage() 1578 message.int32_value = 12345 1579 expected = {'int32Value': 12345} 1580 self.assertEqual(expected, json_format.MessageToDict(message)) 1581 1582 def testJsonName(self): 1583 message = json_format_proto3_pb2.TestCustomJsonName() 1584 message.value = 12345 1585 self.assertEqual( 1586 '{\n "@value": 12345\n}', json_format.MessageToJson(message) 1587 ) 1588 parsed_message = json_format_proto3_pb2.TestCustomJsonName() 1589 self.CheckParseBack(message, parsed_message) 1590 1591 def testSortKeys(self): 1592 # Testing sort_keys is not perfectly working, as by random luck we could 1593 # get the output sorted. We just use a selection of names. 1594 message = json_format_proto3_pb2.TestMessage( 1595 bool_value=True, 1596 int32_value=1, 1597 int64_value=3, 1598 uint32_value=4, 1599 string_value='bla', 1600 ) 1601 self.assertEqual( 1602 json_format.MessageToJson(message, sort_keys=True), 1603 # We use json.dumps() instead of a hardcoded string due to differences 1604 # between Python 2 and Python 3. 1605 json.dumps( 1606 { 1607 'boolValue': True, 1608 'int32Value': 1, 1609 'int64Value': '3', 1610 'uint32Value': 4, 1611 'stringValue': 'bla', 1612 }, 1613 indent=2, 1614 sort_keys=True, 1615 ), 1616 ) 1617 1618 def testNestedRecursiveLimit(self): 1619 message = unittest_pb2.NestedTestAllTypes() 1620 self.assertRaisesRegex( 1621 json_format.ParseError, 1622 'Message too deep. Max recursion depth is 3', 1623 json_format.Parse, 1624 '{"child": {"child": {"child" : {}}}}', 1625 message, 1626 max_recursion_depth=3, 1627 ) 1628 # The following one can pass 1629 json_format.Parse( 1630 '{"payload": {}, "child": {"child":{}}}', message, max_recursion_depth=3 1631 ) 1632 1633 def testJsonNameConflictSerilize(self): 1634 message = more_messages_pb2.ConflictJsonName(value=2) 1635 self.assertEqual( 1636 json.loads('{"old_value": 2}'), 1637 json.loads(json_format.MessageToJson(message)), 1638 ) 1639 1640 new_message = more_messages_pb2.ConflictJsonName(new_value=2) 1641 self.assertEqual( 1642 json.loads('{"value": 2}'), 1643 json.loads(json_format.MessageToJson(new_message)), 1644 ) 1645 1646 def testJsonNameConflictParse(self): 1647 message = more_messages_pb2.ConflictJsonName() 1648 json_format.Parse('{"value": 2}', message) 1649 self.assertEqual(2, message.new_value) 1650 self.assertEqual(0, message.value) 1651 1652 def testJsonNameConflictRoundTrip(self): 1653 message = more_messages_pb2.ConflictJsonName(value=2) 1654 parsed_message = more_messages_pb2.ConflictJsonName() 1655 json_string = json_format.MessageToJson(message) 1656 json_format.Parse(json_string, parsed_message) 1657 self.assertEqual(message, parsed_message) 1658 1659 new_message = more_messages_pb2.ConflictJsonName(new_value=2) 1660 new_parsed_message = more_messages_pb2.ConflictJsonName() 1661 json_string = json_format.MessageToJson(new_message) 1662 json_format.Parse(json_string, new_parsed_message) 1663 self.assertEqual(new_message, new_parsed_message) 1664 1665 def testOtherParseErrors(self): 1666 self.CheckError( 1667 '9', 1668 "Failed to parse JSON: TypeError: 'int' object is not iterable.", 1669 ) 1670 1671 def testManyRecursionsRaisesParseError(self): 1672 num_recursions = 1050 1673 text = ('{"a":' * num_recursions) + '""' + ('}' * num_recursions) 1674 with self.assertRaises(json_format.ParseError): 1675 json_format.Parse(text, json_format_proto3_pb2.TestMessage()) 1676 1677if __name__ == '__main__': 1678 unittest.main() 1679