json_format_test.py 45 KB

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