TestWriterFormatJson.cs 19 KB

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