json_format_test.py 50 KB

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