PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs

https://bitbucket.org/Ecarestia/newtonsoft.json
C# | 2987 lines | 2531 code | 399 blank | 57 comment | 16 complexity | 10293e1b597b93bcf08d97affd061578 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System.Globalization;
  26. #if NET20
  27. using Newtonsoft.Json.Utilities.LinqBridge;
  28. #else
  29. using System.Linq;
  30. #endif
  31. using System.Text;
  32. #if !(DNXCORE50 || PORTABLE40)
  33. using System;
  34. using System.Collections.Generic;
  35. using Newtonsoft.Json.Tests.Serialization;
  36. using Newtonsoft.Json.Tests.TestObjects;
  37. #if DNXCORE50
  38. using Xunit;
  39. using Test = Xunit.FactAttribute;
  40. using Assert = Newtonsoft.Json.Tests.XUnitAssert;
  41. #else
  42. using NUnit.Framework;
  43. #endif
  44. using Newtonsoft.Json;
  45. using System.IO;
  46. using System.Xml;
  47. using Newtonsoft.Json.Converters;
  48. using Newtonsoft.Json.Utilities;
  49. using Newtonsoft.Json.Linq;
  50. #if !NET20
  51. using System.Xml.Linq;
  52. #endif
  53. namespace Newtonsoft.Json.Tests.Converters
  54. {
  55. [TestFixture]
  56. public class XmlNodeConverterTest : TestFixtureBase
  57. {
  58. #if !PORTABLE
  59. private string SerializeXmlNode(XmlNode node)
  60. {
  61. string json = JsonConvert.SerializeXmlNode(node, Formatting.Indented);
  62. XmlNodeReader reader = new XmlNodeReader(node);
  63. #if !NET20
  64. XObject xNode;
  65. if (node is XmlDocument)
  66. {
  67. xNode = XDocument.Load(reader);
  68. }
  69. else if (node is XmlAttribute)
  70. {
  71. XmlAttribute attribute = (XmlAttribute)node;
  72. xNode = new XAttribute(XName.Get(attribute.LocalName, attribute.NamespaceURI), attribute.Value);
  73. }
  74. else
  75. {
  76. reader.MoveToContent();
  77. xNode = XNode.ReadFrom(reader);
  78. }
  79. string linqJson = JsonConvert.SerializeXNode(xNode, Formatting.Indented);
  80. Assert.AreEqual(json, linqJson);
  81. #endif
  82. return json;
  83. }
  84. private XmlNode DeserializeXmlNode(string json)
  85. {
  86. return DeserializeXmlNode(json, null);
  87. }
  88. private XmlNode DeserializeXmlNode(string json, string deserializeRootElementName)
  89. {
  90. JsonTextReader reader;
  91. reader = new JsonTextReader(new StringReader(json));
  92. reader.Read();
  93. XmlNodeConverter converter = new XmlNodeConverter();
  94. if (deserializeRootElementName != null)
  95. {
  96. converter.DeserializeRootElementName = deserializeRootElementName;
  97. }
  98. XmlNode node = (XmlNode)converter.ReadJson(reader, typeof(XmlDocument), null, new JsonSerializer());
  99. #if !NET20
  100. string xmlText = node.OuterXml;
  101. reader = new JsonTextReader(new StringReader(json));
  102. reader.Read();
  103. XDocument d = (XDocument)converter.ReadJson(reader, typeof(XDocument), null, new JsonSerializer());
  104. string linqXmlText = d.ToString(SaveOptions.DisableFormatting);
  105. if (d.Declaration != null)
  106. {
  107. linqXmlText = d.Declaration + linqXmlText;
  108. }
  109. Assert.AreEqual(xmlText, linqXmlText);
  110. #endif
  111. return node;
  112. }
  113. #endif
  114. private string IndentXml(string xml)
  115. {
  116. XmlReader reader = XmlReader.Create(new StringReader(xml));
  117. StringWriter sw = new StringWriter();
  118. XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true });
  119. while (reader.Read())
  120. {
  121. writer.WriteNode(reader, false);
  122. }
  123. writer.Flush();
  124. return sw.ToString();
  125. }
  126. #if !NET20
  127. [Test]
  128. public void SerializeDollarProperty()
  129. {
  130. string json1 = @"{""$"":""test""}";
  131. var doc = JsonConvert.DeserializeXNode(json1);
  132. Assert.AreEqual(@"<_x0024_>test</_x0024_>", doc.ToString());
  133. var json2 = JsonConvert.SerializeXNode(doc);
  134. Assert.AreEqual(json1, json2);
  135. }
  136. [Test]
  137. public void SerializeNonKnownDollarProperty()
  138. {
  139. string json1 = @"{""$JELLY"":""test""}";
  140. var doc = JsonConvert.DeserializeXNode(json1);
  141. Console.WriteLine(doc.ToString());
  142. Assert.AreEqual(@"<_x0024_JELLY>test</_x0024_JELLY>", doc.ToString());
  143. var json2 = JsonConvert.SerializeXNode(doc);
  144. Assert.AreEqual(json1, json2);
  145. }
  146. public class MyModel
  147. {
  148. public string MyProperty { get; set; }
  149. }
  150. [Test]
  151. public void ConvertNullString()
  152. {
  153. JObject json = new JObject();
  154. json["Prop1"] = (string)null;
  155. json["Prop2"] = new MyModel().MyProperty;
  156. var xmlNodeConverter = new XmlNodeConverter { DeserializeRootElementName = "object" };
  157. var jsonSerializerSettings = new JsonSerializerSettings { Converters = new JsonConverter[] { xmlNodeConverter } };
  158. var jsonSerializer = JsonSerializer.CreateDefault(jsonSerializerSettings);
  159. XDocument d = json.ToObject<XDocument>(jsonSerializer);
  160. StringAssert.Equals(@"<object>
  161. <Prop1 />
  162. <Prop2 />
  163. </object>", d.ToString());
  164. }
  165. public class Foo
  166. {
  167. public XElement Bar { get; set; }
  168. }
  169. [Test]
  170. public void SerializeAndDeserializeXElement()
  171. {
  172. Foo foo = new Foo { Bar = null };
  173. string json = JsonConvert.SerializeObject(foo);
  174. Assert.AreEqual(@"{""Bar"":null}", json);
  175. Foo foo2 = JsonConvert.DeserializeObject<Foo>(json);
  176. Assert.IsNull(foo2.Bar);
  177. }
  178. [Test]
  179. public void MultipleNamespacesXDocument()
  180. {
  181. string xml = @"<result xp_0:end=""2014-08-15 13:12:11.9184"" xp_0:start=""2014-08-15 13:11:49.3140"" xp_0:time_diff=""22604.3836"" xmlns:xp_0=""Test1"" p2:end=""2014-08-15 13:13:49.5522"" p2:start=""2014-08-15 13:13:49.0268"" p2:time_diff=""525.4646"" xmlns:p2=""Test2"" />";
  182. XDocument d = XDocument.Parse(xml);
  183. string json = JsonConvert.SerializeObject(d, Formatting.Indented);
  184. StringAssert.AreEqual(@"{
  185. ""result"": {
  186. ""@xp_0:end"": ""2014-08-15 13:12:11.9184"",
  187. ""@xp_0:start"": ""2014-08-15 13:11:49.3140"",
  188. ""@xp_0:time_diff"": ""22604.3836"",
  189. ""@xmlns:xp_0"": ""Test1"",
  190. ""@p2:end"": ""2014-08-15 13:13:49.5522"",
  191. ""@p2:start"": ""2014-08-15 13:13:49.0268"",
  192. ""@p2:time_diff"": ""525.4646"",
  193. ""@xmlns:p2"": ""Test2""
  194. }
  195. }", json);
  196. XDocument doc = JsonConvert.DeserializeObject<XDocument>(json);
  197. StringAssert.AreEqual(xml, doc.ToString());
  198. }
  199. #endif
  200. #if !PORTABLE
  201. [Test]
  202. public void MultipleNamespacesXmlDocument()
  203. {
  204. string xml = @"<result xp_0:end=""2014-08-15 13:12:11.9184"" xp_0:start=""2014-08-15 13:11:49.3140"" xp_0:time_diff=""22604.3836"" xmlns:xp_0=""Test1"" p2:end=""2014-08-15 13:13:49.5522"" p2:start=""2014-08-15 13:13:49.0268"" p2:time_diff=""525.4646"" xmlns:p2=""Test2"" />";
  205. XmlDocument d = new XmlDocument();
  206. d.LoadXml(xml);
  207. string json = JsonConvert.SerializeObject(d, Formatting.Indented);
  208. StringAssert.AreEqual(@"{
  209. ""result"": {
  210. ""@xp_0:end"": ""2014-08-15 13:12:11.9184"",
  211. ""@xp_0:start"": ""2014-08-15 13:11:49.3140"",
  212. ""@xp_0:time_diff"": ""22604.3836"",
  213. ""@xmlns:xp_0"": ""Test1"",
  214. ""@p2:end"": ""2014-08-15 13:13:49.5522"",
  215. ""@p2:start"": ""2014-08-15 13:13:49.0268"",
  216. ""@p2:time_diff"": ""525.4646"",
  217. ""@xmlns:p2"": ""Test2""
  218. }
  219. }", json);
  220. XmlDocument doc = JsonConvert.DeserializeObject<XmlDocument>(json);
  221. StringAssert.AreEqual(xml, doc.OuterXml);
  222. }
  223. [Test]
  224. public void SerializeXmlElement()
  225. {
  226. string xml = @"<payload>
  227. <Country>6</Country>
  228. <FinancialTransactionApprovalRequestUID>79</FinancialTransactionApprovalRequestUID>
  229. <TransactionStatus>Approved</TransactionStatus>
  230. <StatusChangeComment></StatusChangeComment>
  231. <RequestedBy>Someone</RequestedBy>
  232. </payload>";
  233. var xmlDocument = new XmlDocument();
  234. xmlDocument.LoadXml(xml);
  235. var result = xmlDocument.FirstChild.ChildNodes.Cast<XmlNode>().ToArray();
  236. var json = JsonConvert.SerializeObject(result, Formatting.Indented); // <--- fails here with the cast message
  237. StringAssert.AreEqual(@"[
  238. {
  239. ""Country"": ""6""
  240. },
  241. {
  242. ""FinancialTransactionApprovalRequestUID"": ""79""
  243. },
  244. {
  245. ""TransactionStatus"": ""Approved""
  246. },
  247. {
  248. ""StatusChangeComment"": """"
  249. },
  250. {
  251. ""RequestedBy"": ""Someone""
  252. }
  253. ]", json);
  254. }
  255. #endif
  256. #if !NET20
  257. [Test]
  258. public void SerializeXElement()
  259. {
  260. string xml = @"<payload>
  261. <Country>6</Country>
  262. <FinancialTransactionApprovalRequestUID>79</FinancialTransactionApprovalRequestUID>
  263. <TransactionStatus>Approved</TransactionStatus>
  264. <StatusChangeComment></StatusChangeComment>
  265. <RequestedBy>Someone</RequestedBy>
  266. </payload>";
  267. var xmlDocument = XDocument.Parse(xml);
  268. var result = xmlDocument.Root.Nodes().ToArray();
  269. var json = JsonConvert.SerializeObject(result, Formatting.Indented); // <--- fails here with the cast message
  270. StringAssert.AreEqual(@"[
  271. {
  272. ""Country"": ""6""
  273. },
  274. {
  275. ""FinancialTransactionApprovalRequestUID"": ""79""
  276. },
  277. {
  278. ""TransactionStatus"": ""Approved""
  279. },
  280. {
  281. ""StatusChangeComment"": """"
  282. },
  283. {
  284. ""RequestedBy"": ""Someone""
  285. }
  286. ]", json);
  287. }
  288. public class DecimalContainer
  289. {
  290. public decimal Number { get; set; }
  291. }
  292. [Test]
  293. public void FloatParseHandlingDecimal()
  294. {
  295. decimal d = (decimal)Math.PI + 1000000000m;
  296. var x = new DecimalContainer { Number = d };
  297. var json = JsonConvert.SerializeObject(x, Formatting.Indented);
  298. XDocument doc1 = JsonConvert.DeserializeObject<XDocument>(json, new JsonSerializerSettings
  299. {
  300. Converters = { new XmlNodeConverter() },
  301. FloatParseHandling = FloatParseHandling.Decimal
  302. });
  303. var xml = doc1.ToString();
  304. Assert.AreEqual("<Number>1000000003.14159265358979</Number>", xml);
  305. string json2 = JsonConvert.SerializeObject(doc1, Formatting.Indented);
  306. DecimalContainer x2 = JsonConvert.DeserializeObject<DecimalContainer>(json2);
  307. Assert.AreEqual(x.Number, x2.Number);
  308. }
  309. public class DateTimeOffsetContainer
  310. {
  311. public DateTimeOffset Date { get; set; }
  312. }
  313. [Test]
  314. public void DateTimeParseHandlingOffset()
  315. {
  316. DateTimeOffset d = new DateTimeOffset(2012, 12, 12, 12, 44, 1, TimeSpan.FromHours(12).Add(TimeSpan.FromMinutes(34)));
  317. var x = new DateTimeOffsetContainer { Date = d };
  318. var json = JsonConvert.SerializeObject(x, Formatting.Indented);
  319. XDocument doc1 = JsonConvert.DeserializeObject<XDocument>(json, new JsonSerializerSettings
  320. {
  321. Converters = { new XmlNodeConverter() },
  322. DateParseHandling = DateParseHandling.DateTimeOffset
  323. });
  324. var xml = doc1.ToString();
  325. Assert.AreEqual("<Date>2012-12-12T12:44:01+12:34</Date>", xml);
  326. string json2 = JsonConvert.SerializeObject(doc1, Formatting.Indented);
  327. DateTimeOffsetContainer x2 = JsonConvert.DeserializeObject<DateTimeOffsetContainer>(json2);
  328. Assert.AreEqual(x.Date, x2.Date);
  329. }
  330. [Test]
  331. public void GroupElementsOfTheSameName()
  332. {
  333. string xml = "<root><p>Text1<span>Span1</span> <span>Span2</span> Text2</p></root>";
  334. string json = JsonConvert.SerializeXNode(XElement.Parse(xml));
  335. Assert.AreEqual(@"{""root"":{""p"":{""#text"":[""Text1"","" Text2""],""span"":[""Span1"",""Span2""]}}}", json);
  336. XDocument doc = JsonConvert.DeserializeXNode(json);
  337. StringAssert.AreEqual(@"<root>
  338. <p>Text1 Text2<span>Span1</span><span>Span2</span></p>
  339. </root>", doc.ToString());
  340. }
  341. #if !PORTABLE
  342. [Test]
  343. public void SerializeEmptyDocument()
  344. {
  345. XmlDocument doc = new XmlDocument();
  346. doc.LoadXml("<root />");
  347. string json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true);
  348. Assert.AreEqual("null", json);
  349. doc = new XmlDocument();
  350. doc.LoadXml("<root></root>");
  351. json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true);
  352. Assert.AreEqual(@"""""", json);
  353. XDocument doc1 = XDocument.Parse("<root />");
  354. json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true);
  355. Assert.AreEqual("null", json);
  356. doc1 = XDocument.Parse("<root></root>");
  357. json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true);
  358. Assert.AreEqual(@"""""", json);
  359. }
  360. #endif
  361. [Test]
  362. public void SerializeAndDeserializeXmlWithNamespaceInChildrenAndNoValueInChildren()
  363. {
  364. var xmlString = @"<root>
  365. <b xmlns='http://www.example.com/ns'/>
  366. <c>AAA</c>
  367. <test>adad</test>
  368. </root>";
  369. var xml = XElement.Parse(xmlString);
  370. var json1 = JsonConvert.SerializeXNode(xml);
  371. var xmlBack = JsonConvert.DeserializeObject<XElement>(json1);
  372. var equals = XElement.DeepEquals(xmlBack, xml);
  373. Assert.IsTrue(equals);
  374. }
  375. #if !PORTABLE
  376. [Test]
  377. public void DeserializeUndeclaredNamespacePrefix()
  378. {
  379. XmlDocument doc = JsonConvert.DeserializeXmlNode("{ A: { '@xsi:nil': true } }");
  380. Assert.AreEqual(@"<A nil=""true"" />", doc.OuterXml);
  381. XDocument xdoc = JsonConvert.DeserializeXNode("{ A: { '@xsi:nil': true } }");
  382. Assert.AreEqual(doc.OuterXml, xdoc.ToString());
  383. }
  384. #endif
  385. #endif
  386. #if !PORTABLE
  387. [Test]
  388. public void DeserializeMultipleRootElements()
  389. {
  390. string json = @"{
  391. ""Id"": 1,
  392. ""Email"": ""james@example.com"",
  393. ""Active"": true,
  394. ""CreatedDate"": ""2013-01-20T00:00:00Z"",
  395. ""Roles"": [
  396. ""User"",
  397. ""Admin""
  398. ],
  399. ""Team"": {
  400. ""Id"": 2,
  401. ""Name"": ""Software Developers"",
  402. ""Description"": ""Creators of fine software products and services.""
  403. }
  404. }";
  405. ExceptionAssert.Throws<JsonSerializationException>(
  406. () => { JsonConvert.DeserializeXmlNode(json); },
  407. "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'Email', line 3, position 13.");
  408. }
  409. [Test]
  410. public void DocumentSerializeIndented()
  411. {
  412. string xml = @"<?xml version=""1.0"" standalone=""no""?>
  413. <?xml-stylesheet href=""classic.xsl"" type=""text/xml""?>
  414. <span class=""vevent"">
  415. <a class=""url"" href=""http://www.web2con.com/"">
  416. <span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
  417. <abbr class=""dtstart"" title=""2005-10-05"">October 5</abbr>
  418. <abbr class=""dtend"" title=""2005-10-08"">7</abbr>
  419. <span class=""location"">Argent Hotel, San Francisco, CA</span>
  420. </a>
  421. </span>";
  422. XmlDocument doc = new XmlDocument();
  423. doc.LoadXml(xml);
  424. string jsonText = SerializeXmlNode(doc);
  425. string expected = @"{
  426. ""?xml"": {
  427. ""@version"": ""1.0"",
  428. ""@standalone"": ""no""
  429. },
  430. ""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
  431. ""span"": {
  432. ""@class"": ""vevent"",
  433. ""a"": {
  434. ""@class"": ""url"",
  435. ""@href"": ""http://www.web2con.com/"",
  436. ""span"": [
  437. {
  438. ""@class"": ""summary"",
  439. ""#text"": ""Web 2.0 Conference"",
  440. ""#cdata-section"": ""my escaped text""
  441. },
  442. {
  443. ""@class"": ""location"",
  444. ""#text"": ""Argent Hotel, San Francisco, CA""
  445. }
  446. ],
  447. ""abbr"": [
  448. {
  449. ""@class"": ""dtstart"",
  450. ""@title"": ""2005-10-05"",
  451. ""#text"": ""October 5""
  452. },
  453. {
  454. ""@class"": ""dtend"",
  455. ""@title"": ""2005-10-08"",
  456. ""#text"": ""7""
  457. }
  458. ]
  459. }
  460. }
  461. }";
  462. StringAssert.AreEqual(expected, jsonText);
  463. }
  464. [Test]
  465. public void SerializeNodeTypes()
  466. {
  467. XmlDocument doc = new XmlDocument();
  468. string jsonText;
  469. string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
  470. <xs:schema xs:id=""SomeID""
  471. xmlns=""""
  472. xmlns:xs=""http://www.w3.org/2001/XMLSchema""
  473. xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
  474. <xs:element name=""MyDataSet"" msdata:IsDataSet=""true"">
  475. </xs:element>
  476. </xs:schema>";
  477. XmlDocument document = new XmlDocument();
  478. document.LoadXml(xml);
  479. // XmlAttribute
  480. XmlAttribute attribute = document.DocumentElement.ChildNodes[0].Attributes["IsDataSet", "urn:schemas-microsoft-com:xml-msdata"];
  481. attribute.Value = "true";
  482. jsonText = JsonConvert.SerializeXmlNode(attribute);
  483. Assert.AreEqual(@"{""@msdata:IsDataSet"":""true""}", jsonText);
  484. #if !NET20
  485. XDocument d = XDocument.Parse(xml);
  486. XAttribute a = d.Root.Element("{http://www.w3.org/2001/XMLSchema}element").Attribute("{urn:schemas-microsoft-com:xml-msdata}IsDataSet");
  487. jsonText = JsonConvert.SerializeXNode(a);
  488. Assert.AreEqual(@"{""@msdata:IsDataSet"":""true""}", jsonText);
  489. #endif
  490. // XmlProcessingInstruction
  491. XmlProcessingInstruction instruction = doc.CreateProcessingInstruction("xml-stylesheet", @"href=""classic.xsl"" type=""text/xml""");
  492. jsonText = JsonConvert.SerializeXmlNode(instruction);
  493. Assert.AreEqual(@"{""?xml-stylesheet"":""href=\""classic.xsl\"" type=\""text/xml\""""}", jsonText);
  494. // XmlProcessingInstruction
  495. XmlCDataSection cDataSection = doc.CreateCDataSection("<Kiwi>true</Kiwi>");
  496. jsonText = JsonConvert.SerializeXmlNode(cDataSection);
  497. Assert.AreEqual(@"{""#cdata-section"":""<Kiwi>true</Kiwi>""}", jsonText);
  498. // XmlElement
  499. XmlElement element = doc.CreateElement("xs", "Choice", "http://www.w3.org/2001/XMLSchema");
  500. element.SetAttributeNode(doc.CreateAttribute("msdata", "IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));
  501. XmlAttribute aa = doc.CreateAttribute(@"xmlns", "xs", "http://www.w3.org/2000/xmlns/");
  502. aa.Value = "http://www.w3.org/2001/XMLSchema";
  503. element.SetAttributeNode(aa);
  504. aa = doc.CreateAttribute(@"xmlns", "msdata", "http://www.w3.org/2000/xmlns/");
  505. aa.Value = "urn:schemas-microsoft-com:xml-msdata";
  506. element.SetAttributeNode(aa);
  507. element.AppendChild(instruction);
  508. element.AppendChild(cDataSection);
  509. doc.AppendChild(element);
  510. jsonText = JsonConvert.SerializeXmlNode(element, Formatting.Indented);
  511. StringAssert.AreEqual(@"{
  512. ""xs:Choice"": {
  513. ""@msdata:IsDataSet"": """",
  514. ""@xmlns:xs"": ""http://www.w3.org/2001/XMLSchema"",
  515. ""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
  516. ""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
  517. ""#cdata-section"": ""<Kiwi>true</Kiwi>""
  518. }
  519. }", jsonText);
  520. }
  521. [Test]
  522. public void SerializeNodeTypes_Encoding()
  523. {
  524. XmlNode node = DeserializeXmlNode(@"{
  525. ""xs!:Choice!"": {
  526. ""@msdata:IsDataSet!"": """",
  527. ""@xmlns:xs!"": ""http://www.w3.org/2001/XMLSchema"",
  528. ""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
  529. ""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
  530. ""#cdata-section"": ""<Kiwi>true</Kiwi>""
  531. }
  532. }");
  533. Assert.AreEqual(@"<xs_x0021_:Choice_x0021_ msdata:IsDataSet_x0021_="""" xmlns:xs_x0021_=""http://www.w3.org/2001/XMLSchema"" xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata""><?xml-stylesheet href=""classic.xsl"" type=""text/xml""?><![CDATA[<Kiwi>true</Kiwi>]]></xs_x0021_:Choice_x0021_>", node.InnerXml);
  534. string json = SerializeXmlNode(node);
  535. StringAssert.AreEqual(@"{
  536. ""xs!:Choice!"": {
  537. ""@msdata:IsDataSet!"": """",
  538. ""@xmlns:xs!"": ""http://www.w3.org/2001/XMLSchema"",
  539. ""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
  540. ""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
  541. ""#cdata-section"": ""<Kiwi>true</Kiwi>""
  542. }
  543. }", json);
  544. }
  545. [Test]
  546. public void DocumentFragmentSerialize()
  547. {
  548. XmlDocument doc = new XmlDocument();
  549. XmlDocumentFragment fragement = doc.CreateDocumentFragment();
  550. fragement.InnerXml = "<Item>widget</Item><Item>widget</Item>";
  551. string jsonText = JsonConvert.SerializeXmlNode(fragement);
  552. string expected = @"{""Item"":[""widget"",""widget""]}";
  553. Assert.AreEqual(expected, jsonText);
  554. }
  555. [Test]
  556. public void XmlDocumentTypeSerialize()
  557. {
  558. string xml = @"<?xml version=""1.0"" encoding=""utf-8""?><!DOCTYPE STOCKQUOTE PUBLIC ""-//W3C//DTD StockQuote 1.5//EN"" ""http://www.idontexistnopenopewhatnope123.org/dtd/stockquote_1.5.dtd""><STOCKQUOTE ROWCOUNT=""2""><RESULT><ROW><ASK>0</ASK><BID>0</BID><CHANGE>-16.310</CHANGE><COMPANYNAME>Dow Jones</COMPANYNAME><DATETIME>2014-04-17 15:50:37</DATETIME><DIVIDEND>0</DIVIDEND><EPS>0</EPS><EXCHANGE></EXCHANGE><HIGH>16460.490</HIGH><LASTDATETIME>2014-04-17 15:50:37</LASTDATETIME><LASTPRICE>16408.540</LASTPRICE><LOW>16368.140</LOW><OPEN>16424.140</OPEN><PCHANGE>-0.099</PCHANGE><PE>0</PE><PREVIOUSCLOSE>16424.850</PREVIOUSCLOSE><SHARES>0</SHARES><TICKER>DJII</TICKER><TRADES>0</TRADES><VOLUME>136188700</VOLUME><YEARHIGH>11309.000</YEARHIGH><YEARLOW>9302.280</YEARLOW><YIELD>0</YIELD></ROW><ROW><ASK>0</ASK><BID>0</BID><CHANGE>9.290</CHANGE><COMPANYNAME>NASDAQ</COMPANYNAME><DATETIME>2014-04-17 15:40:01</DATETIME><DIVIDEND>0</DIVIDEND><EPS>0</EPS><EXCHANGE></EXCHANGE><HIGH>4110.460</HIGH><LASTDATETIME>2014-04-17 15:40:01</LASTDATETIME><LASTPRICE>4095.520</LASTPRICE><LOW>4064.700</LOW><OPEN>4080.300</OPEN><PCHANGE>0.227</PCHANGE><PE>0</PE><PREVIOUSCLOSE>4086.230</PREVIOUSCLOSE><SHARES>0</SHARES><TICKER>COMP</TICKER><TRADES>0</TRADES><VOLUME>1784210100</VOLUME><YEARHIGH>4371.710</YEARHIGH><YEARLOW>3154.960</YEARLOW><YIELD>0</YIELD></ROW></RESULT><STATUS>Couldn't find ticker: SPIC?</STATUS><STATUSCODE>2</STATUSCODE></STOCKQUOTE>";
  559. string expected = @"{
  560. ""?xml"": {
  561. ""@version"": ""1.0"",
  562. ""@encoding"": ""utf-8""
  563. },
  564. ""!DOCTYPE"": {
  565. ""@name"": ""STOCKQUOTE"",
  566. ""@public"": ""-//W3C//DTD StockQuote 1.5//EN"",
  567. ""@system"": ""http://www.idontexistnopenopewhatnope123.org/dtd/stockquote_1.5.dtd""
  568. },
  569. ""STOCKQUOTE"": {
  570. ""@ROWCOUNT"": ""2"",
  571. ""RESULT"": {
  572. ""ROW"": [
  573. {
  574. ""ASK"": ""0"",
  575. ""BID"": ""0"",
  576. ""CHANGE"": ""-16.310"",
  577. ""COMPANYNAME"": ""Dow Jones"",
  578. ""DATETIME"": ""2014-04-17 15:50:37"",
  579. ""DIVIDEND"": ""0"",
  580. ""EPS"": ""0"",
  581. ""EXCHANGE"": """",
  582. ""HIGH"": ""16460.490"",
  583. ""LASTDATETIME"": ""2014-04-17 15:50:37"",
  584. ""LASTPRICE"": ""16408.540"",
  585. ""LOW"": ""16368.140"",
  586. ""OPEN"": ""16424.140"",
  587. ""PCHANGE"": ""-0.099"",
  588. ""PE"": ""0"",
  589. ""PREVIOUSCLOSE"": ""16424.850"",
  590. ""SHARES"": ""0"",
  591. ""TICKER"": ""DJII"",
  592. ""TRADES"": ""0"",
  593. ""VOLUME"": ""136188700"",
  594. ""YEARHIGH"": ""11309.000"",
  595. ""YEARLOW"": ""9302.280"",
  596. ""YIELD"": ""0""
  597. },
  598. {
  599. ""ASK"": ""0"",
  600. ""BID"": ""0"",
  601. ""CHANGE"": ""9.290"",
  602. ""COMPANYNAME"": ""NASDAQ"",
  603. ""DATETIME"": ""2014-04-17 15:40:01"",
  604. ""DIVIDEND"": ""0"",
  605. ""EPS"": ""0"",
  606. ""EXCHANGE"": """",
  607. ""HIGH"": ""4110.460"",
  608. ""LASTDATETIME"": ""2014-04-17 15:40:01"",
  609. ""LASTPRICE"": ""4095.520"",
  610. ""LOW"": ""4064.700"",
  611. ""OPEN"": ""4080.300"",
  612. ""PCHANGE"": ""0.227"",
  613. ""PE"": ""0"",
  614. ""PREVIOUSCLOSE"": ""4086.230"",
  615. ""SHARES"": ""0"",
  616. ""TICKER"": ""COMP"",
  617. ""TRADES"": ""0"",
  618. ""VOLUME"": ""1784210100"",
  619. ""YEARHIGH"": ""4371.710"",
  620. ""YEARLOW"": ""3154.960"",
  621. ""YIELD"": ""0""
  622. }
  623. ]
  624. },
  625. ""STATUS"": ""Couldn't find ticker: SPIC?"",
  626. ""STATUSCODE"": ""2""
  627. }
  628. }";
  629. XmlDocument doc1 = new XmlDocument();
  630. doc1.XmlResolver = null;
  631. doc1.LoadXml(xml);
  632. string json1 = JsonConvert.SerializeXmlNode(doc1, Formatting.Indented);
  633. StringAssert.AreEqual(expected, json1);
  634. XmlDocument doc11 = JsonConvert.DeserializeXmlNode(json1);
  635. StringAssert.AreEqual(xml, ToStringWithDeclaration(doc11));
  636. #if !NET20
  637. XDocument doc2 = XDocument.Parse(xml);
  638. string json2 = JsonConvert.SerializeXNode(doc2, Formatting.Indented);
  639. StringAssert.AreEqual(expected, json2);
  640. XDocument doc22 = JsonConvert.DeserializeXNode(json2);
  641. StringAssert.AreEqual(xml, ToStringWithDeclaration(doc22));
  642. #endif
  643. }
  644. public class Utf8StringWriter : StringWriter
  645. {
  646. public override Encoding Encoding
  647. {
  648. get { return Encoding.UTF8; }
  649. }
  650. public Utf8StringWriter(StringBuilder sb) : base(sb)
  651. {
  652. }
  653. }
  654. #if !NET20
  655. public static string ToStringWithDeclaration(XDocument doc, bool indent = false)
  656. {
  657. StringBuilder builder = new StringBuilder();
  658. using (var writer = XmlWriter.Create(new Utf8StringWriter(builder), new XmlWriterSettings { Indent = indent }))
  659. {
  660. doc.Save(writer);
  661. }
  662. return builder.ToString();
  663. }
  664. #endif
  665. public static string ToStringWithDeclaration(XmlDocument doc, bool indent = false)
  666. {
  667. StringBuilder builder = new StringBuilder();
  668. using (var writer = XmlWriter.Create(new Utf8StringWriter(builder), new XmlWriterSettings { Indent = indent }))
  669. {
  670. doc.Save(writer);
  671. }
  672. return builder.ToString();
  673. }
  674. [Test]
  675. public void NamespaceSerializeDeserialize()
  676. {
  677. string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
  678. <xs:schema xs:id=""SomeID""
  679. xmlns=""""
  680. xmlns:xs=""http://www.w3.org/2001/XMLSchema""
  681. xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
  682. <xs:element name=""MyDataSet"" msdata:IsDataSet=""true"">
  683. <xs:complexType>
  684. <xs:choice maxOccurs=""unbounded"">
  685. <xs:element name=""customers"" >
  686. <xs:complexType >
  687. <xs:sequence>
  688. <xs:element name=""CustomerID"" type=""xs:integer""
  689. minOccurs=""0"" />
  690. <xs:element name=""CompanyName"" type=""xs:string""
  691. minOccurs=""0"" />
  692. <xs:element name=""Phone"" type=""xs:string"" />
  693. </xs:sequence>
  694. </xs:complexType>
  695. </xs:element>
  696. </xs:choice>
  697. </xs:complexType>
  698. </xs:element>
  699. </xs:schema>";
  700. XmlDocument doc = new XmlDocument();
  701. doc.LoadXml(xml);
  702. string jsonText = SerializeXmlNode(doc);
  703. string expected = @"{
  704. ""?xml"": {
  705. ""@version"": ""1.0"",
  706. ""@encoding"": ""utf-8""
  707. },
  708. ""xs:schema"": {
  709. ""@xs:id"": ""SomeID"",
  710. ""@xmlns"": """",
  711. ""@xmlns:xs"": ""http://www.w3.org/2001/XMLSchema"",
  712. ""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
  713. ""xs:element"": {
  714. ""@name"": ""MyDataSet"",
  715. ""@msdata:IsDataSet"": ""true"",
  716. ""xs:complexType"": {
  717. ""xs:choice"": {
  718. ""@maxOccurs"": ""unbounded"",
  719. ""xs:element"": {
  720. ""@name"": ""customers"",
  721. ""xs:complexType"": {
  722. ""xs:sequence"": {
  723. ""xs:element"": [
  724. {
  725. ""@name"": ""CustomerID"",
  726. ""@type"": ""xs:integer"",
  727. ""@minOccurs"": ""0""
  728. },
  729. {
  730. ""@name"": ""CompanyName"",
  731. ""@type"": ""xs:string"",
  732. ""@minOccurs"": ""0""
  733. },
  734. {
  735. ""@name"": ""Phone"",
  736. ""@type"": ""xs:string""
  737. }
  738. ]
  739. }
  740. }
  741. }
  742. }
  743. }
  744. }
  745. }
  746. }";
  747. StringAssert.AreEqual(expected, jsonText);
  748. XmlDocument deserializedDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  749. Assert.AreEqual(doc.InnerXml, deserializedDoc.InnerXml);
  750. }
  751. [Test]
  752. public void DocumentDeserialize()
  753. {
  754. string jsonText = @"{
  755. ""?xml"": {
  756. ""@version"": ""1.0"",
  757. ""@standalone"": ""no""
  758. },
  759. ""span"": {
  760. ""@class"": ""vevent"",
  761. ""a"": {
  762. ""@class"": ""url"",
  763. ""span"": {
  764. ""@class"": ""summary"",
  765. ""#text"": ""Web 2.0 Conference"",
  766. ""#cdata-section"": ""my escaped text""
  767. },
  768. ""@href"": ""http://www.web2con.com/""
  769. }
  770. }
  771. }";
  772. XmlDocument doc = (XmlDocument)DeserializeXmlNode(jsonText);
  773. string expected = @"<?xml version=""1.0"" standalone=""no""?>
  774. <span class=""vevent"">
  775. <a class=""url"" href=""http://www.web2con.com/"">
  776. <span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
  777. </a>
  778. </span>";
  779. string formattedXml = GetIndentedInnerXml(doc);
  780. StringAssert.AreEqual(expected, formattedXml);
  781. }
  782. private string GetIndentedInnerXml(XmlNode node)
  783. {
  784. XmlWriterSettings settings = new XmlWriterSettings();
  785. settings.Indent = true;
  786. StringWriter sw = new StringWriter();
  787. using (XmlWriter writer = XmlWriter.Create(sw, settings))
  788. {
  789. node.WriteTo(writer);
  790. }
  791. return sw.ToString();
  792. }
  793. [Test]
  794. public void SingleTextNode()
  795. {
  796. string xml = @"<?xml version=""1.0"" standalone=""no""?>
  797. <root>
  798. <person id=""1"">
  799. <name>Alan</name>
  800. <url>http://www.google.com</url>
  801. </person>
  802. <person id=""2"">
  803. <name>Louis</name>
  804. <url>http://www.yahoo.com</url>
  805. </person>
  806. </root>";
  807. XmlDocument doc = new XmlDocument();
  808. doc.LoadXml(xml);
  809. string jsonText = SerializeXmlNode(doc);
  810. XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  811. Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
  812. }
  813. [Test]
  814. public void EmptyNode()
  815. {
  816. string xml = @"<?xml version=""1.0"" standalone=""no""?>
  817. <root>
  818. <person id=""1"">
  819. <name>Alan</name>
  820. <url />
  821. </person>
  822. <person id=""2"">
  823. <name>Louis</name>
  824. <url>http://www.yahoo.com</url>
  825. </person>
  826. </root>";
  827. XmlDocument doc = new XmlDocument();
  828. doc.LoadXml(xml);
  829. string jsonText = SerializeXmlNode(doc);
  830. StringAssert.AreEqual(@"{
  831. ""?xml"": {
  832. ""@version"": ""1.0"",
  833. ""@standalone"": ""no""
  834. },
  835. ""root"": {
  836. ""person"": [
  837. {
  838. ""@id"": ""1"",
  839. ""name"": ""Alan"",
  840. ""url"": null
  841. },
  842. {
  843. ""@id"": ""2"",
  844. ""name"": ""Louis"",
  845. ""url"": ""http://www.yahoo.com""
  846. }
  847. ]
  848. }
  849. }", jsonText);
  850. XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  851. Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
  852. }
  853. [Test]
  854. public void OtherElementDataTypes()
  855. {
  856. string jsonText = @"{""?xml"":{""@version"":""1.0"",""@standalone"":""no""},""root"":{""person"":[{""@id"":""1"",""Float"":2.5,""Integer"":99},{""Boolean"":true,""@id"":""2"",""date"":""\/Date(954374400000)\/""}]}}";
  857. XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  858. string expected = @"<?xml version=""1.0"" standalone=""no""?><root><person id=""1""><Float>2.5</Float><Integer>99</Integer></person><person id=""2""><Boolean>true</Boolean><date>2000-03-30T00:00:00Z</date></person></root>";
  859. Assert.AreEqual(expected, newDoc.InnerXml);
  860. }
  861. [Test]
  862. public void NoRootObject()
  863. {
  864. ExceptionAssert.Throws<JsonSerializationException>(() => { XmlDocument newDoc = (XmlDocument)JsonConvert.DeserializeXmlNode(@"[1]"); }, "XmlNodeConverter can only convert JSON that begins with an object.");
  865. }
  866. [Test]
  867. public void RootObjectMultipleProperties()
  868. {
  869. ExceptionAssert.Throws<JsonSerializationException>(
  870. () => { XmlDocument newDoc = (XmlDocument)JsonConvert.DeserializeXmlNode(@"{Prop1:1,Prop2:2}"); },
  871. "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'Prop2', line 1, position 15.");
  872. }
  873. [Test]
  874. public void JavaScriptConstructor()
  875. {
  876. string jsonText = @"{root:{r:new Date(34343, 55)}}";
  877. XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  878. string expected = @"<root><r><Date>34343</Date><Date>55</Date></r></root>";
  879. Assert.AreEqual(expected, newDoc.InnerXml);
  880. string json = SerializeXmlNode(newDoc);
  881. expected = @"{
  882. ""root"": {
  883. ""r"": {
  884. ""Date"": [
  885. ""34343"",
  886. ""55""
  887. ]
  888. }
  889. }
  890. }";
  891. StringAssert.AreEqual(expected, json);
  892. }
  893. [Test]
  894. public void ForceJsonArray()
  895. {
  896. string arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
  897. <person id=""1"">
  898. <name>Alan</name>
  899. <url>http://www.google.com</url>
  900. <role json:Array=""true"">Admin</role>
  901. </person>
  902. </root>";
  903. XmlDocument arrayDoc = new XmlDocument();
  904. arrayDoc.LoadXml(arrayXml);
  905. string arrayJsonText = SerializeXmlNode(arrayDoc);
  906. string expected = @"{
  907. ""root"": {
  908. ""person"": {
  909. ""@id"": ""1"",
  910. ""name"": ""Alan"",
  911. ""url"": ""http://www.google.com"",
  912. ""role"": [
  913. ""Admin""
  914. ]
  915. }
  916. }
  917. }";
  918. StringAssert.AreEqual(expected, arrayJsonText);
  919. arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
  920. <person id=""1"">
  921. <name>Alan</name>
  922. <url>http://www.google.com</url>
  923. <role json:Array=""true"">Admin1</role>
  924. <role json:Array=""true"">Admin2</role>
  925. </person>
  926. </root>";
  927. arrayDoc = new XmlDocument();
  928. arrayDoc.LoadXml(arrayXml);
  929. arrayJsonText = SerializeXmlNode(arrayDoc);
  930. expected = @"{
  931. ""root"": {
  932. ""person"": {
  933. ""@id"": ""1"",
  934. ""name"": ""Alan"",
  935. ""url"": ""http://www.google.com"",
  936. ""role"": [
  937. ""Admin1"",
  938. ""Admin2""
  939. ]
  940. }
  941. }
  942. }";
  943. StringAssert.AreEqual(expected, arrayJsonText);
  944. arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
  945. <person id=""1"">
  946. <name>Alan</name>
  947. <url>http://www.google.com</url>
  948. <role json:Array=""false"">Admin1</role>
  949. </person>
  950. </root>";
  951. arrayDoc = new XmlDocument();
  952. arrayDoc.LoadXml(arrayXml);
  953. arrayJsonText = SerializeXmlNode(arrayDoc);
  954. expected = @"{
  955. ""root"": {
  956. ""person"": {
  957. ""@id"": ""1"",
  958. ""name"": ""Alan"",
  959. ""url"": ""http://www.google.com"",
  960. ""role"": ""Admin1""
  961. }
  962. }
  963. }";
  964. StringAssert.AreEqual(expected, arrayJsonText);
  965. arrayXml = @"<root>
  966. <person id=""1"">
  967. <name>Alan</name>
  968. <url>http://www.google.com</url>
  969. <role json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">Admin</role>
  970. </person>
  971. </root>";
  972. arrayDoc = new XmlDocument();
  973. arrayDoc.LoadXml(arrayXml);
  974. arrayJsonText = SerializeXmlNode(arrayDoc);
  975. expected = @"{
  976. ""root"": {
  977. ""person"": {
  978. ""@id"": ""1"",
  979. ""name"": ""Alan"",
  980. ""url"": ""http://www.google.com"",
  981. ""role"": [
  982. ""Admin""
  983. ]
  984. }
  985. }
  986. }";
  987. StringAssert.AreEqual(expected, arrayJsonText);
  988. }
  989. [Test]
  990. public void MultipleRootPropertiesXmlDocument()
  991. {
  992. string json = @"{""count"": 773840,""photos"": null}";
  993. ExceptionAssert.Throws<JsonSerializationException>(
  994. () => { JsonConvert.DeserializeXmlNode(json); },
  995. "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'photos', line 1, position 26.");
  996. }
  997. #endif
  998. #if !NET20
  999. [Test]
  1000. public void MultipleRootPropertiesXDocument()
  1001. {
  1002. string json = @"{""count"": 773840,""photos"": null}";
  1003. ExceptionAssert.Throws<JsonSerializationException>(
  1004. () => { JsonConvert.DeserializeXNode(json); },
  1005. "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path 'photos', line 1, position 26.");
  1006. }
  1007. #endif
  1008. [Test]
  1009. public void MultipleRootPropertiesAddRootElement()
  1010. {
  1011. string json = @"{""count"": 773840,""photos"": 773840}";
  1012. #if !PORTABLE
  1013. XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
  1014. Assert.AreEqual(@"<myRoot><count>773840</count><photos>773840</photos></myRoot>", newDoc.InnerXml);
  1015. #endif
  1016. #if !NET20
  1017. XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
  1018. Assert.AreEqual(@"<myRoot><count>773840</count><photos>773840</photos></myRoot>", newXDoc.ToString(SaveOptions.DisableFormatting));
  1019. #endif
  1020. }
  1021. [Test]
  1022. public void NestedArrays()
  1023. {
  1024. string json = @"{
  1025. ""available_sizes"": [
  1026. [
  1027. ""assets/images/resized/0001/1070/11070v1-max-150x150.jpg"",
  1028. ""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
  1029. ],
  1030. [
  1031. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg"",
  1032. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
  1033. ],
  1034. [
  1035. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
  1036. ]
  1037. ]
  1038. }";
  1039. #if !PORTABLE
  1040. XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
  1041. string xml = IndentXml(newDoc.InnerXml);
  1042. StringAssert.AreEqual(@"<myRoot>
  1043. <available_sizes>
  1044. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1045. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1046. </available_sizes>
  1047. <available_sizes>
  1048. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1049. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1050. </available_sizes>
  1051. <available_sizes>
  1052. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1053. </available_sizes>
  1054. </myRoot>", IndentXml(newDoc.InnerXml));
  1055. #endif
  1056. #if !NET20
  1057. XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
  1058. StringAssert.AreEqual(@"<myRoot>
  1059. <available_sizes>
  1060. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1061. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1062. </available_sizes>
  1063. <available_sizes>
  1064. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1065. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1066. </available_sizes>
  1067. <available_sizes>
  1068. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1069. </available_sizes>
  1070. </myRoot>", IndentXml(newXDoc.ToString(SaveOptions.DisableFormatting)));
  1071. #endif
  1072. #if !PORTABLE
  1073. string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented);
  1074. Console.WriteLine(newJson);
  1075. #endif
  1076. }
  1077. [Test]
  1078. public void RoundTripNestedArrays()
  1079. {
  1080. string json = @"{
  1081. ""available_sizes"": [
  1082. [
  1083. ""assets/images/resized/0001/1070/11070v1-max-150x150.jpg"",
  1084. ""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
  1085. ],
  1086. [
  1087. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg"",
  1088. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
  1089. ],
  1090. [
  1091. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
  1092. ]
  1093. ]
  1094. }";
  1095. #if !PORTABLE
  1096. XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot", true);
  1097. StringAssert.AreEqual(@"<myRoot>
  1098. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1099. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1100. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1101. </available_sizes>
  1102. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1103. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1104. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1105. </available_sizes>
  1106. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1107. <available_sizes json:Array=""true"">assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1108. </available_sizes>
  1109. </myRoot>", IndentXml(newDoc.InnerXml));
  1110. #endif
  1111. #if !NET20
  1112. XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot", true);
  1113. StringAssert.AreEqual(@"<myRoot>
  1114. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1115. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1116. <available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
  1117. </available_sizes>
  1118. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1119. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1120. <available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1121. </available_sizes>
  1122. <available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
  1123. <available_sizes json:Array=""true"">assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
  1124. </available_sizes>
  1125. </myRoot>", IndentXml(newXDoc.ToString(SaveOptions.DisableFormatting)));
  1126. #endif
  1127. #if !PORTABLE
  1128. string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented, true);
  1129. StringAssert.AreEqual(json, newJson);
  1130. #endif
  1131. }
  1132. [Test]
  1133. public void MultipleNestedArraysToXml()
  1134. {
  1135. string json = @"{
  1136. ""available_sizes"": [
  1137. [
  1138. [113, 150],
  1139. ""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
  1140. ],
  1141. [
  1142. [189, 250],
  1143. ""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
  1144. ],
  1145. [
  1146. [341, 450],
  1147. ""assets/images/resized/0001/1070/11070v1-max-450x450.jpg""
  1148. ]
  1149. ]
  1150. }";
  1151. #if !PORTABLE
  1152. XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
  1153. Assert.AreEqual(@"<myRoot><available_sizes><available_sizes><available_sizes>113</available_sizes><available_sizes>150</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>189</available_sizes><available_sizes>250</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>341</available_sizes><available_sizes>450</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-450x450.jpg</available_sizes></available_sizes></myRoot>", newDoc.InnerXml);
  1154. #endif
  1155. #if !NET20
  1156. XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
  1157. Assert.AreEqual(@"<myRoot><available_sizes><available_sizes><available_sizes>113</available_sizes><available_sizes>150</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>189</available_sizes><available_sizes>250</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes></available_sizes><available_sizes><available_sizes><available_sizes>341</available_sizes><available_sizes>450</available_sizes></available_sizes><available_sizes>assets/images/resized/0001/1070/11070v1-max-450x450.jpg</available_sizes></available_sizes></myRoot>", newXDoc.ToString(SaveOptions.DisableFormatting));
  1158. #endif
  1159. }
  1160. #if !PORTABLE
  1161. [Test]
  1162. public void Encoding()
  1163. {
  1164. XmlDocument doc = new XmlDocument();
  1165. doc.LoadXml(@"<name>O""Connor</name>"); // i use "" so it will be easier to see the problem
  1166. string json = SerializeXmlNode(doc);
  1167. StringAssert.AreEqual(@"{
  1168. ""name"": ""O\""Connor""
  1169. }", json);
  1170. }
  1171. #endif
  1172. #if !PORTABLE
  1173. [Test]
  1174. public void SerializeComment()
  1175. {
  1176. string xml = @"<span class=""vevent"">
  1177. <a class=""url"" href=""http://www.web2con.com/""><!-- Hi --><span>Text</span></a><!-- Hi! -->
  1178. </span>";
  1179. XmlDocument doc = new XmlDocument();
  1180. doc.LoadXml(xml);
  1181. string jsonText = SerializeXmlNode(doc);
  1182. string expected = @"{
  1183. ""span"": {
  1184. ""@class"": ""vevent"",
  1185. ""a"": {
  1186. ""@class"": ""url"",
  1187. ""@href"": ""http://www.web2con.com/""/* Hi */,
  1188. ""span"": ""Text""
  1189. }/* Hi! */
  1190. }
  1191. }";
  1192. StringAssert.AreEqual(expected, jsonText);
  1193. XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
  1194. Assert.AreEqual(@"<span class=""vevent""><a class=""url"" href=""http://www.web2con.com/""><!-- Hi --><span>Text</span></a><!-- Hi! --></span>", newDoc.InnerXml);
  1195. }
  1196. [Test]
  1197. public void SerializeExample()
  1198. {
  1199. string xml = @"<?xml version=""1.0"" standalone=""no""?>
  1200. <root>
  1201. <person id=""1"">
  1202. <name>Alan</name>
  1203. <url>http://www.google.com</url>
  1204. </person>
  1205. <person id=""2"">
  1206. <name>Louis</name>
  1207. <url>http://www.yahoo.com</url>
  1208. </person>
  1209. </root>";
  1210. XmlDocument doc = new XmlDocument();
  1211. doc.LoadXml(xml);
  1212. string jsonText = SerializeXmlNode(doc);
  1213. // {
  1214. // "?xml": {
  1215. // "@version": "1.0",
  1216. // "@standalone": "no"
  1217. // },
  1218. // "root": {
  1219. // "person": [
  1220. // {
  1221. // "@id": "1",
  1222. // "name": "Alan",
  1223. // "url": "http://www.google.com"
  1224. // },
  1225. // {
  1226. // "@id": "2",
  1227. // "name": "Louis",
  1228. // "url": "http://www.yahoo.com"
  1229. // }
  1230. // ]
  1231. // }
  1232. // }
  1233. // format
  1234. jsonText = JObject.Parse(jsonText).ToString();
  1235. StringAssert.AreEqual(@"{
  1236. ""?xml"": {
  1237. ""@version"": ""1.0"",
  1238. ""@standalone"": ""no""
  1239. },
  1240. ""root"": {
  1241. ""person"": [
  1242. {
  1243. ""@id"": ""1"",
  1244. ""name"": ""Alan"",
  1245. ""url"": ""http://www.google.com""
  1246. },
  1247. {
  1248. ""@id"": ""2"",

Large files files are truncated, but you can click here to view the full file