json_format_test.py 49 KB

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