json_format_test.py 41 KB

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