TestWriterFormatJson.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using Google.ProtocolBuffers.Serialization;
  5. using NUnit.Framework;
  6. using Google.ProtocolBuffers.TestProtos;
  7. namespace Google.ProtocolBuffers
  8. {
  9. [TestFixture]
  10. public class TestWriterFormatJson
  11. {
  12. [Test]
  13. public void Example_FromJson()
  14. {
  15. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  16. builder.MergeFromJson(@"{""valid"":true}");
  17. TestXmlMessage message = builder.Build();
  18. Assert.AreEqual(true, message.Valid);
  19. }
  20. [Test]
  21. public void Example_ToJson()
  22. {
  23. TestXmlMessage message =
  24. TestXmlMessage.CreateBuilder()
  25. .SetValid(true)
  26. .Build();
  27. string json = message.ToJson();
  28. Assert.AreEqual(@"{""valid"":true}", json);
  29. }
  30. [Test]
  31. public void Example_WriteJsonUsingICodedOutputStream()
  32. {
  33. TestXmlMessage message =
  34. TestXmlMessage.CreateBuilder()
  35. .SetValid(true)
  36. .Build();
  37. using (TextWriter output = new StringWriter())
  38. {
  39. ICodedOutputStream writer = JsonFormatWriter.CreateInstance(output);
  40. writer.WriteMessageStart(); //manually begin the message, output is '{'
  41. writer.Flush();
  42. Assert.AreEqual("{", output.ToString());
  43. ICodedOutputStream stream = writer;
  44. message.WriteTo(stream); //write the message normally
  45. writer.Flush();
  46. Assert.AreEqual(@"{""valid"":true", output.ToString());
  47. writer.WriteMessageEnd(); //manually write the end message '}'
  48. Assert.AreEqual(@"{""valid"":true}", output.ToString());
  49. }
  50. }
  51. [Test]
  52. public void Example_ReadJsonUsingICodedInputStream()
  53. {
  54. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  55. ICodedInputStream reader = JsonFormatReader.CreateInstance(@"{""valid"":true}");
  56. reader.ReadMessageStart(); //manually read the begin the message '{'
  57. builder.MergeFrom(reader); //write the message normally
  58. reader.ReadMessageEnd(); //manually read the end message '}'
  59. }
  60. protected string Content;
  61. [System.Diagnostics.DebuggerNonUserCode]
  62. protected void FormatterAssert<TMessage>(TMessage message, params string[] expecting) where TMessage : IMessageLite
  63. {
  64. StringWriter sw = new StringWriter();
  65. JsonFormatWriter.CreateInstance(sw).WriteMessage(message);
  66. Content = sw.ToString();
  67. ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
  68. UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);
  69. IMessageLite copy =
  70. JsonFormatReader.CreateInstance(Content)
  71. .Merge(message.WeakCreateBuilderForType(), registry).WeakBuild();
  72. Assert.AreEqual(typeof(TMessage), copy.GetType());
  73. Assert.AreEqual(message, copy);
  74. foreach (string expect in expecting)
  75. Assert.IsTrue(Content.IndexOf(expect) >= 0, "Expected to find content '{0}' in: \r\n{1}", expect, Content);
  76. }
  77. [Test]
  78. public void TestToJsonParseFromJson()
  79. {
  80. TestAllTypes msg = new TestAllTypes.Builder().SetDefaultBool(true).Build();
  81. string json = msg.ToJson();
  82. Assert.AreEqual("{\"default_bool\":true}", json);
  83. TestAllTypes copy = new TestAllTypes.Builder().MergeFromJson(json).Build();
  84. Assert.IsTrue(copy.HasDefaultBool && copy.DefaultBool);
  85. Assert.AreEqual(msg, copy);
  86. }
  87. [Test]
  88. public void TestToJsonParseFromJsonReader()
  89. {
  90. TestAllTypes msg = new TestAllTypes.Builder().SetDefaultBool(true).Build();
  91. string json = msg.ToJson();
  92. Assert.AreEqual("{\"default_bool\":true}", json);
  93. TestAllTypes copy = new TestAllTypes.Builder().MergeFromJson(new StringReader(json)).Build();
  94. Assert.IsTrue(copy.HasDefaultBool && copy.DefaultBool);
  95. Assert.AreEqual(msg, copy);
  96. }
  97. [Test]
  98. public void TestJsonFormatted()
  99. {
  100. TestXmlMessage message = TestXmlMessage.CreateBuilder()
  101. .SetValid(true)
  102. .SetNumber(0x1010)
  103. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder())
  104. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.ONE))
  105. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.ONE).AddOptions(EnumOptions.TWO))
  106. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().SetBinary(ByteString.CopyFromUtf8("abc")))
  107. .Build();
  108. StringWriter sw = new StringWriter();
  109. JsonFormatWriter.CreateInstance(sw).Formatted()
  110. .WriteMessage(message);
  111. string json = sw.ToString();
  112. TestXmlMessage copy = JsonFormatReader.CreateInstance(json)
  113. .Merge(TestXmlMessage.CreateBuilder()).Build();
  114. Assert.AreEqual(message, copy);
  115. }
  116. [Test]
  117. public void TestEmptyMessage()
  118. {
  119. FormatterAssert(
  120. TestXmlChild.CreateBuilder()
  121. .Build(),
  122. @"{}"
  123. );
  124. }
  125. [Test]
  126. public void TestRepeatedField()
  127. {
  128. FormatterAssert(
  129. TestXmlChild.CreateBuilder()
  130. .AddOptions(EnumOptions.ONE)
  131. .AddOptions(EnumOptions.TWO)
  132. .Build(),
  133. @"{""options"":[""ONE"",""TWO""]}"
  134. );
  135. }
  136. [Test]
  137. public void TestNestedEmptyMessage()
  138. {
  139. FormatterAssert(
  140. TestXmlMessage.CreateBuilder()
  141. .SetChild(TestXmlChild.CreateBuilder().Build())
  142. .Build(),
  143. @"{""child"":{}}"
  144. );
  145. }
  146. [Test]
  147. public void TestNestedMessage()
  148. {
  149. FormatterAssert(
  150. TestXmlMessage.CreateBuilder()
  151. .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.TWO).Build())
  152. .Build(),
  153. @"{""child"":{""options"":[""TWO""]}}"
  154. );
  155. }
  156. [Test]
  157. public void TestBooleanTypes()
  158. {
  159. FormatterAssert(
  160. TestXmlMessage.CreateBuilder()
  161. .SetValid(true)
  162. .Build(),
  163. @"{""valid"":true}"
  164. );
  165. }
  166. [Test]
  167. public void TestFullMessage()
  168. {
  169. FormatterAssert(
  170. TestXmlMessage.CreateBuilder()
  171. .SetValid(true)
  172. .SetText("text")
  173. .AddTextlines("a")
  174. .AddTextlines("b")
  175. .AddTextlines("c")
  176. .SetNumber(0x1010101010)
  177. .AddNumbers(1)
  178. .AddNumbers(2)
  179. .AddNumbers(3)
  180. .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
  181. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
  182. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
  183. .Build(),
  184. @"""text"":""text""",
  185. @"[""a"",""b"",""c""]",
  186. @"[1,2,3]",
  187. @"""child"":{",
  188. @"""children"":[{",
  189. @"AA==",
  190. @"AAA=",
  191. @"AAAA",
  192. 0x1010101010L.ToString()
  193. );
  194. }
  195. [Test]
  196. public void TestMessageWithXmlText()
  197. {
  198. FormatterAssert(
  199. TestXmlMessage.CreateBuilder()
  200. .SetText("<text></text>")
  201. .Build(),
  202. @"{""text"":""<text><\/text>""}"
  203. );
  204. }
  205. [Test]
  206. public void TestWithEscapeChars()
  207. {
  208. FormatterAssert(
  209. TestXmlMessage.CreateBuilder()
  210. .SetText(" \t <- \"leading space and trailing\" -> \\ \xef54 \x0000 \xFF \xFFFF \b \f \r \n \t ")
  211. .Build(),
  212. "{\"text\":\" \\t <- \\\"leading space and trailing\\\" -> \\\\ \\uef54 \\u0000 \\u00ff \\uffff \\b \\f \\r \\n \\t \"}"
  213. );
  214. }
  215. [Test]
  216. public void TestWithExtensionText()
  217. {
  218. FormatterAssert(
  219. TestXmlMessage.CreateBuilder()
  220. .SetValid(false)
  221. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
  222. .Build(),
  223. @"{""valid"":false,""extension_text"":"" extension text value ! ""}"
  224. );
  225. }
  226. [Test]
  227. public void TestWithExtensionNumber()
  228. {
  229. FormatterAssert(
  230. TestXmlMessage.CreateBuilder()
  231. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage,
  232. new TestXmlExtension.Builder().SetNumber(42).Build())
  233. .Build(),
  234. @"{""number"":42}"
  235. );
  236. }
  237. [Test]
  238. public void TestWithExtensionArray()
  239. {
  240. FormatterAssert(
  241. TestXmlMessage.CreateBuilder()
  242. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  243. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  244. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  245. .Build(),
  246. @"{""extension_number"":[100,101,102]}"
  247. );
  248. }
  249. [Test]
  250. public void TestWithExtensionEnum()
  251. {
  252. FormatterAssert(
  253. TestXmlMessage.CreateBuilder()
  254. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  255. .Build(),
  256. @"{""extension_enum"":""ONE""}"
  257. );
  258. }
  259. [Test]
  260. public void TestMessageWithExtensions()
  261. {
  262. FormatterAssert(
  263. TestXmlMessage.CreateBuilder()
  264. .SetValid(true)
  265. .SetText("text")
  266. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, "extension text")
  267. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
  268. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  269. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  270. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  271. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  272. .Build(),
  273. @"""text"":""text""",
  274. @"""valid"":true",
  275. @"""extension_enum"":""ONE""",
  276. @"""extension_text"":""extension text""",
  277. @"""extension_number"":[100,101,102]",
  278. @"""extension_message"":{""number"":42}"
  279. );
  280. }
  281. [Test]
  282. public void TestMessageMissingExtensions()
  283. {
  284. TestXmlMessage original = TestXmlMessage.CreateBuilder()
  285. .SetValid(true)
  286. .SetText("text")
  287. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
  288. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
  289. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  290. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  291. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  292. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  293. .Build();
  294. TestXmlMessage message = original.ToBuilder()
  295. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText)
  296. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage)
  297. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber)
  298. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum)
  299. .Build();
  300. JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
  301. writer.WriteMessage(original);
  302. Content = writer.ToString();
  303. IMessageLite copy = JsonFormatReader.CreateInstance(Content)
  304. .Merge(message.CreateBuilderForType()).Build();
  305. Assert.AreNotEqual(original, message);
  306. Assert.AreNotEqual(original, copy);
  307. Assert.AreEqual(message, copy);
  308. }
  309. [Test]
  310. public void TestMergeFields()
  311. {
  312. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  313. builder.MergeFrom(JsonFormatReader.CreateInstance("\"valid\": true"));
  314. builder.MergeFrom(JsonFormatReader.CreateInstance("\"text\": \"text\", \"number\": \"411\""));
  315. Assert.AreEqual(true, builder.Valid);
  316. Assert.AreEqual("text", builder.Text);
  317. Assert.AreEqual(411, builder.Number);
  318. }
  319. [Test]
  320. public void TestMessageArray()
  321. {
  322. JsonFormatWriter writer = JsonFormatWriter.CreateInstance().Formatted();
  323. using (writer.StartArray())
  324. {
  325. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(1).AddTextlines("a").Build());
  326. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(2).AddTextlines("b").Build());
  327. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
  328. }
  329. string json = writer.ToString();
  330. JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
  331. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  332. int ordinal = 0;
  333. foreach (JsonFormatReader r in reader.EnumerateArray())
  334. {
  335. r.Merge(builder);
  336. Assert.AreEqual(++ordinal, builder.Number);
  337. }
  338. Assert.AreEqual(3, ordinal);
  339. Assert.AreEqual(3, builder.TextlinesCount);
  340. }
  341. [Test]
  342. public void TestNestedMessageArray()
  343. {
  344. JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
  345. using (writer.StartArray())
  346. {
  347. using (writer.StartArray())
  348. {
  349. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(1).AddTextlines("a").Build());
  350. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(2).AddTextlines("b").Build());
  351. }
  352. using (writer.StartArray())
  353. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
  354. }
  355. string json = writer.ToString();
  356. JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
  357. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  358. int ordinal = 0;
  359. foreach (JsonFormatReader r in reader.EnumerateArray())
  360. foreach (JsonFormatReader r2 in r.EnumerateArray())
  361. {
  362. r2.Merge(builder);
  363. Assert.AreEqual(++ordinal, builder.Number);
  364. }
  365. Assert.AreEqual(3, ordinal);
  366. Assert.AreEqual(3, builder.TextlinesCount);
  367. }
  368. [Test]
  369. public void TestReadWriteJsonWithoutRoot()
  370. {
  371. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  372. TestXmlMessage message = builder.SetText("abc").SetNumber(123).Build();
  373. string Json;
  374. using (StringWriter sw = new StringWriter())
  375. {
  376. ICodedOutputStream output = JsonFormatWriter.CreateInstance(sw);
  377. message.WriteTo(output);
  378. output.Flush();
  379. Json = sw.ToString();
  380. }
  381. Assert.AreEqual(@"""text"":""abc"",""number"":123", Json);
  382. ICodedInputStream input = JsonFormatReader.CreateInstance(Json);
  383. TestXmlMessage copy = TestXmlMessage.CreateBuilder().MergeFrom(input).Build();
  384. Assert.AreEqual(message, copy);
  385. }
  386. [Test,ExpectedException(typeof(RecursionLimitExceededException))]
  387. public void TestRecursiveLimit()
  388. {
  389. StringBuilder sb = new StringBuilder(8192);
  390. for (int i = 0; i < 80; i++)
  391. sb.Append("{\"child\":");
  392. TestXmlRescursive msg = new TestXmlRescursive.Builder().MergeFromJson(sb.ToString()).Build();
  393. }
  394. [Test, ExpectedException(typeof(FormatException))]
  395. public void FailWithEmptyText()
  396. {
  397. JsonFormatReader.CreateInstance("")
  398. .Merge(TestXmlMessage.CreateBuilder());
  399. }
  400. [Test, ExpectedException(typeof(FormatException))]
  401. public void FailWithUnexpectedValue()
  402. {
  403. JsonFormatReader.CreateInstance("{{}}")
  404. .Merge(TestXmlMessage.CreateBuilder());
  405. }
  406. [Test, ExpectedException(typeof(FormatException))]
  407. public void FailWithUnQuotedName()
  408. {
  409. JsonFormatReader.CreateInstance("{name:{}}")
  410. .Merge(TestXmlMessage.CreateBuilder());
  411. }
  412. [Test, ExpectedException(typeof(FormatException))]
  413. public void FailWithUnexpectedType()
  414. {
  415. JsonFormatReader.CreateInstance("{\"valid\":{}}")
  416. .Merge(TestXmlMessage.CreateBuilder());
  417. }
  418. }
  419. }