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