3444 lines
119 KiB
C#
3444 lines
119 KiB
C#
#region License
|
||
// Copyright (c) 2007 James Newton-King
|
||
//
|
||
// Permission is hereby granted, free of charge, to any person
|
||
// obtaining a copy of this software and associated documentation
|
||
// files (the "Software"), to deal in the Software without
|
||
// restriction, including without limitation the rights to use,
|
||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
// copies of the Software, and to permit persons to whom the
|
||
// Software is furnished to do so, subject to the following
|
||
// conditions:
|
||
//
|
||
// The above copyright notice and this permission notice shall be
|
||
// included in all copies or substantial portions of the Software.
|
||
//
|
||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
// OTHER DEALINGS IN THE SOFTWARE.
|
||
#endregion
|
||
|
||
#if !(DNXCORE50 || PORTABLE40) || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
using System.Globalization;
|
||
#if NET20
|
||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||
#else
|
||
using System.Linq;
|
||
#endif
|
||
using System.Text;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using Newtonsoft.Json.Tests.Serialization;
|
||
using Newtonsoft.Json.Tests.TestObjects;
|
||
#if DNXCORE50
|
||
using Xunit;
|
||
using Test = Xunit.FactAttribute;
|
||
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
|
||
#else
|
||
using NUnit.Framework;
|
||
#endif
|
||
using Newtonsoft.Json;
|
||
using System.IO;
|
||
using System.Xml;
|
||
using Newtonsoft.Json.Converters;
|
||
using Newtonsoft.Json.Utilities;
|
||
using Newtonsoft.Json.Linq;
|
||
#if !NET20
|
||
using System.Xml.Linq;
|
||
|
||
#endif
|
||
|
||
namespace Newtonsoft.Json.Tests.Converters
|
||
{
|
||
[TestFixture]
|
||
public class XmlNodeConverterTest : TestFixtureBase
|
||
{
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
private string SerializeXmlNode(XmlNode node)
|
||
{
|
||
string json = JsonConvert.SerializeXmlNode(node, Formatting.Indented);
|
||
|
||
#if !(NET20)
|
||
#if !NETSTANDARD1_3
|
||
XmlReader reader = new XmlNodeReader(node);
|
||
#else
|
||
StringReader sr = new StringReader(node.OuterXml);
|
||
XmlReader reader = XmlReader.Create(sr);
|
||
#endif
|
||
|
||
XObject xNode;
|
||
if (node is XmlDocument)
|
||
{
|
||
xNode = XDocument.Load(reader);
|
||
}
|
||
else if (node is XmlAttribute)
|
||
{
|
||
XmlAttribute attribute = (XmlAttribute)node;
|
||
xNode = new XAttribute(XName.Get(attribute.LocalName, attribute.NamespaceURI), attribute.Value);
|
||
}
|
||
else
|
||
{
|
||
reader.MoveToContent();
|
||
xNode = XNode.ReadFrom(reader);
|
||
}
|
||
|
||
string linqJson = JsonConvert.SerializeXNode(xNode, Formatting.Indented);
|
||
|
||
Assert.AreEqual(json, linqJson);
|
||
#endif
|
||
|
||
return json;
|
||
}
|
||
|
||
private XmlNode DeserializeXmlNode(string json)
|
||
{
|
||
return DeserializeXmlNode(json, null);
|
||
}
|
||
|
||
private XmlNode DeserializeXmlNode(string json, string deserializeRootElementName)
|
||
{
|
||
JsonTextReader reader;
|
||
|
||
reader = new JsonTextReader(new StringReader(json));
|
||
reader.Read();
|
||
XmlNodeConverter converter = new XmlNodeConverter();
|
||
if (deserializeRootElementName != null)
|
||
{
|
||
converter.DeserializeRootElementName = deserializeRootElementName;
|
||
}
|
||
|
||
XmlNode node = (XmlNode)converter.ReadJson(reader, typeof(XmlDocument), null, new JsonSerializer());
|
||
|
||
#if !NET20
|
||
string xmlText = node.OuterXml;
|
||
|
||
reader = new JsonTextReader(new StringReader(json));
|
||
reader.Read();
|
||
XDocument d = (XDocument)converter.ReadJson(reader, typeof(XDocument), null, new JsonSerializer());
|
||
|
||
string linqXmlText = d.ToString(SaveOptions.DisableFormatting);
|
||
if (d.Declaration != null)
|
||
{
|
||
linqXmlText = d.Declaration + linqXmlText;
|
||
}
|
||
|
||
Assert.AreEqual(xmlText, linqXmlText);
|
||
#endif
|
||
|
||
return node;
|
||
}
|
||
#endif
|
||
|
||
private string IndentXml(string xml)
|
||
{
|
||
XmlReader reader = XmlReader.Create(new StringReader(xml));
|
||
|
||
StringWriter sw = new StringWriter();
|
||
XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true });
|
||
|
||
while (reader.Read())
|
||
{
|
||
writer.WriteNode(reader, false);
|
||
}
|
||
|
||
writer.Flush();
|
||
|
||
return sw.ToString();
|
||
}
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void DeserializeXmlNode_DefaultDate()
|
||
{
|
||
XmlDocument xmlNode = JsonConvert.DeserializeXmlNode("{Time: \"0001-01-01T00:00:00\"}");
|
||
|
||
Assert.AreEqual("<Time>0001-01-01T00:00:00</Time>", xmlNode.OuterXml);
|
||
}
|
||
|
||
[Test]
|
||
public void XmlNode_Null()
|
||
{
|
||
string json = JsonConvert.SerializeXmlNode(null);
|
||
|
||
Assert.AreEqual("null", json);
|
||
}
|
||
|
||
[Test]
|
||
public void XmlNode_Roundtrip_PropertyNameWithColon()
|
||
{
|
||
const string initialJson = @"{""Be:fore:After!"":""Value!""}";
|
||
|
||
XmlDocument xmlNode = JsonConvert.DeserializeXmlNode(initialJson, null, false, true);
|
||
|
||
Assert.AreEqual("<Be_x003A_fore_x003A_After_x0021_>Value!</Be_x003A_fore_x003A_After_x0021_>", xmlNode.OuterXml);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(xmlNode);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XmlNode_Roundtrip_PropertyNameWithEscapedValue()
|
||
{
|
||
const string initialJson = @"{""BeforeAfter!"":""Value!""}";
|
||
|
||
XmlDocument xmlNode = JsonConvert.DeserializeXmlNode(initialJson);
|
||
|
||
Assert.AreEqual("<BeforeAfter_x0021_>Value!</BeforeAfter_x0021_>", xmlNode.OuterXml);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(xmlNode);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XmlNode_EncodeSpecialCharacters()
|
||
{
|
||
string initialJson = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""span"": {
|
||
""@class"": ""vevent"",
|
||
""a"": {
|
||
""@class"": ""url"",
|
||
""@href"": ""http://www.web2con.com/"",
|
||
""span"": [
|
||
{
|
||
""@class"": ""summary"",
|
||
""#text"": ""Web 2.0 Conference"",
|
||
""#cdata-section"": ""my escaped text""
|
||
},
|
||
{
|
||
""@class"": ""location"",
|
||
""#text"": ""Argent Hotel, San Francisco, CA""
|
||
}
|
||
],
|
||
""abbr"": [
|
||
{
|
||
""@class"": ""dtstart"",
|
||
""@title"": ""2005-10-05"",
|
||
""#text"": ""October 5""
|
||
},
|
||
{
|
||
""@class"": ""dtend"",
|
||
""@title"": ""2005-10-08"",
|
||
""#text"": ""7""
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
|
||
XmlDocument xmlNode = JsonConvert.DeserializeXmlNode(initialJson, "root", false, true);
|
||
|
||
StringAssert.AreEqual(@"<root>
|
||
<_x003F_xml>
|
||
<_x0040_version>1.0</_x0040_version>
|
||
<_x0040_standalone>no</_x0040_standalone>
|
||
</_x003F_xml>
|
||
<_x003F_xml-stylesheet>href=""classic.xsl"" type=""text/xml""</_x003F_xml-stylesheet>
|
||
<span>
|
||
<_x0040_class>vevent</_x0040_class>
|
||
<a>
|
||
<_x0040_class>url</_x0040_class>
|
||
<_x0040_href>http://www.web2con.com/</_x0040_href>
|
||
<span>
|
||
<_x0040_class>summary</_x0040_class>
|
||
<_x0023_text>Web 2.0 Conference</_x0023_text>
|
||
<_x0023_cdata-section>my escaped text</_x0023_cdata-section>
|
||
</span>
|
||
<span>
|
||
<_x0040_class>location</_x0040_class>
|
||
<_x0023_text>Argent Hotel, San Francisco, CA</_x0023_text>
|
||
</span>
|
||
<abbr>
|
||
<_x0040_class>dtstart</_x0040_class>
|
||
<_x0040_title>2005-10-05</_x0040_title>
|
||
<_x0023_text>October 5</_x0023_text>
|
||
</abbr>
|
||
<abbr>
|
||
<_x0040_class>dtend</_x0040_class>
|
||
<_x0040_title>2005-10-08</_x0040_title>
|
||
<_x0023_text>7</_x0023_text>
|
||
</abbr>
|
||
</a>
|
||
</span>
|
||
</root>", IndentXml(xmlNode.OuterXml));
|
||
|
||
string json = JsonConvert.SerializeXmlNode(xmlNode, Formatting.Indented, true);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XmlNode_UnescapeTextContent()
|
||
{
|
||
XmlDocument xmlNode = new XmlDocument();
|
||
xmlNode.LoadXml("<root>A > B</root>");
|
||
|
||
string json = JsonConvert.SerializeXmlNode(xmlNode);
|
||
|
||
Assert.AreEqual(@"{""root"":""A > B""}", json);
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void DeserializeXNode_DefaultDate()
|
||
{
|
||
var xmlNode = JsonConvert.DeserializeXNode("{Time: \"0001-01-01T00:00:00\"}");
|
||
|
||
Assert.AreEqual("<Time>0001-01-01T00:00:00</Time>", xmlNode.ToString());
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void WriteJsonNull()
|
||
{
|
||
StringWriter sw = new StringWriter();
|
||
JsonTextWriter jsonWriter = new JsonTextWriter(sw);
|
||
|
||
XmlNodeConverter converter = new XmlNodeConverter();
|
||
converter.WriteJson(jsonWriter, null, null);
|
||
|
||
StringAssert.AreEqual(@"null", sw.ToString());
|
||
}
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void XNode_Null()
|
||
{
|
||
string json = JsonConvert.SerializeXNode(null);
|
||
|
||
Assert.AreEqual("null", json);
|
||
}
|
||
|
||
[Test]
|
||
public void XNode_UnescapeTextContent()
|
||
{
|
||
XElement xmlNode = XElement.Parse("<root>A > B</root>");
|
||
|
||
string json = JsonConvert.SerializeXNode(xmlNode);
|
||
|
||
Assert.AreEqual(@"{""root"":""A > B""}", json);
|
||
}
|
||
|
||
[Test]
|
||
public void XNode_Roundtrip_PropertyNameWithColon()
|
||
{
|
||
const string initialJson = @"{""Be:fore:After!"":""Value!""}";
|
||
|
||
XDocument xmlNode = JsonConvert.DeserializeXNode(initialJson, null, false, true);
|
||
|
||
Assert.AreEqual("<Be_x003A_fore_x003A_After_x0021_>Value!</Be_x003A_fore_x003A_After_x0021_>", xmlNode.ToString());
|
||
|
||
string json = JsonConvert.SerializeXNode(xmlNode);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XNode_Roundtrip_PropertyNameWithEscapedValue()
|
||
{
|
||
const string initialJson = @"{""BeforeAfter!"":""Value!""}";
|
||
|
||
XDocument xmlNode = JsonConvert.DeserializeXNode(initialJson);
|
||
|
||
Assert.AreEqual("<BeforeAfter_x0021_>Value!</BeforeAfter_x0021_>", xmlNode.ToString());
|
||
|
||
string json = JsonConvert.SerializeXNode(xmlNode);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XNode_EncodeSpecialCharacters()
|
||
{
|
||
string initialJson = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""span"": {
|
||
""@class"": ""vevent"",
|
||
""a"": {
|
||
""@class"": ""url"",
|
||
""@href"": ""http://www.web2con.com/"",
|
||
""span"": [
|
||
{
|
||
""@class"": ""summary"",
|
||
""#text"": ""Web 2.0 Conference"",
|
||
""#cdata-section"": ""my escaped text""
|
||
},
|
||
{
|
||
""@class"": ""location"",
|
||
""#text"": ""Argent Hotel, San Francisco, CA""
|
||
}
|
||
],
|
||
""abbr"": [
|
||
{
|
||
""@class"": ""dtstart"",
|
||
""@title"": ""2005-10-05"",
|
||
""#text"": ""October 5""
|
||
},
|
||
{
|
||
""@class"": ""dtend"",
|
||
""@title"": ""2005-10-08"",
|
||
""#text"": ""7""
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
|
||
XDocument xmlNode = JsonConvert.DeserializeXNode(initialJson, "root", false, true);
|
||
|
||
StringAssert.AreEqual(@"<root>
|
||
<_x003F_xml>
|
||
<_x0040_version>1.0</_x0040_version>
|
||
<_x0040_standalone>no</_x0040_standalone>
|
||
</_x003F_xml>
|
||
<_x003F_xml-stylesheet>href=""classic.xsl"" type=""text/xml""</_x003F_xml-stylesheet>
|
||
<span>
|
||
<_x0040_class>vevent</_x0040_class>
|
||
<a>
|
||
<_x0040_class>url</_x0040_class>
|
||
<_x0040_href>http://www.web2con.com/</_x0040_href>
|
||
<span>
|
||
<_x0040_class>summary</_x0040_class>
|
||
<_x0023_text>Web 2.0 Conference</_x0023_text>
|
||
<_x0023_cdata-section>my escaped text</_x0023_cdata-section>
|
||
</span>
|
||
<span>
|
||
<_x0040_class>location</_x0040_class>
|
||
<_x0023_text>Argent Hotel, San Francisco, CA</_x0023_text>
|
||
</span>
|
||
<abbr>
|
||
<_x0040_class>dtstart</_x0040_class>
|
||
<_x0040_title>2005-10-05</_x0040_title>
|
||
<_x0023_text>October 5</_x0023_text>
|
||
</abbr>
|
||
<abbr>
|
||
<_x0040_class>dtend</_x0040_class>
|
||
<_x0040_title>2005-10-08</_x0040_title>
|
||
<_x0023_text>7</_x0023_text>
|
||
</abbr>
|
||
</a>
|
||
</span>
|
||
</root>", xmlNode.ToString());
|
||
|
||
string json = JsonConvert.SerializeXNode(xmlNode, Formatting.Indented, true);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void XNode_MetadataArray_EncodeSpecialCharacters()
|
||
{
|
||
string initialJson = @"{
|
||
""$id"": ""1"",
|
||
""$values"": [
|
||
""1"",
|
||
""2"",
|
||
""3"",
|
||
""4"",
|
||
""5""
|
||
]
|
||
}";
|
||
|
||
XDocument xmlNode = JsonConvert.DeserializeXNode(initialJson, "root", false, true);
|
||
|
||
StringAssert.AreEqual(@"<root>
|
||
<_x0024_id>1</_x0024_id>
|
||
<_x0024_values>1</_x0024_values>
|
||
<_x0024_values>2</_x0024_values>
|
||
<_x0024_values>3</_x0024_values>
|
||
<_x0024_values>4</_x0024_values>
|
||
<_x0024_values>5</_x0024_values>
|
||
</root>", xmlNode.ToString());
|
||
|
||
string json = JsonConvert.SerializeXNode(xmlNode, Formatting.Indented, true);
|
||
|
||
Assert.AreEqual(initialJson, json);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDollarProperty()
|
||
{
|
||
string json1 = @"{""$"":""test""}";
|
||
|
||
var doc = JsonConvert.DeserializeXNode(json1);
|
||
|
||
Assert.AreEqual(@"<_x0024_>test</_x0024_>", doc.ToString());
|
||
|
||
var json2 = JsonConvert.SerializeXNode(doc);
|
||
|
||
Assert.AreEqual(json1, json2);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeNonKnownDollarProperty()
|
||
{
|
||
string json1 = @"{""$JELLY"":""test""}";
|
||
|
||
var doc = JsonConvert.DeserializeXNode(json1);
|
||
|
||
Console.WriteLine(doc.ToString());
|
||
|
||
Assert.AreEqual(@"<_x0024_JELLY>test</_x0024_JELLY>", doc.ToString());
|
||
|
||
var json2 = JsonConvert.SerializeXNode(doc);
|
||
|
||
Assert.AreEqual(json1, json2);
|
||
}
|
||
|
||
public class MyModel
|
||
{
|
||
public string MyProperty { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void ConvertNullString()
|
||
{
|
||
JObject json = new JObject();
|
||
json["Prop1"] = (string)null;
|
||
json["Prop2"] = new MyModel().MyProperty;
|
||
|
||
var xmlNodeConverter = new XmlNodeConverter { DeserializeRootElementName = "object" };
|
||
var jsonSerializerSettings = new JsonSerializerSettings { Converters = new JsonConverter[] { xmlNodeConverter } };
|
||
var jsonSerializer = JsonSerializer.CreateDefault(jsonSerializerSettings);
|
||
XDocument d = json.ToObject<XDocument>(jsonSerializer);
|
||
|
||
StringAssert.Equals(@"<object>
|
||
<Prop1 />
|
||
<Prop2 />
|
||
</object>", d.ToString());
|
||
}
|
||
|
||
public class Foo
|
||
{
|
||
public XElement Bar { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeAndDeserializeXElement()
|
||
{
|
||
Foo foo = new Foo { Bar = null };
|
||
string json = JsonConvert.SerializeObject(foo);
|
||
|
||
Assert.AreEqual(@"{""Bar"":null}", json);
|
||
Foo foo2 = JsonConvert.DeserializeObject<Foo>(json);
|
||
|
||
Assert.IsNull(foo2.Bar);
|
||
}
|
||
|
||
[Test]
|
||
public void MultipleNamespacesXDocument()
|
||
{
|
||
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"" />";
|
||
|
||
XDocument d = XDocument.Parse(xml);
|
||
|
||
string json = JsonConvert.SerializeObject(d, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""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""
|
||
}
|
||
}", json);
|
||
|
||
XDocument doc = JsonConvert.DeserializeObject<XDocument>(json);
|
||
|
||
StringAssert.AreEqual(xml, doc.ToString());
|
||
}
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void MultipleNamespacesXmlDocument()
|
||
{
|
||
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"" />";
|
||
|
||
XmlDocument d = new XmlDocument();
|
||
d.LoadXml(xml);
|
||
|
||
string json = JsonConvert.SerializeObject(d, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""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""
|
||
}
|
||
}", json);
|
||
|
||
XmlDocument doc = JsonConvert.DeserializeObject<XmlDocument>(json);
|
||
|
||
StringAssert.AreEqual(xml, doc.OuterXml);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeXmlElement()
|
||
{
|
||
string xml = @"<payload>
|
||
<Country>6</Country>
|
||
<FinancialTransactionApprovalRequestUID>79</FinancialTransactionApprovalRequestUID>
|
||
<TransactionStatus>Approved</TransactionStatus>
|
||
<StatusChangeComment></StatusChangeComment>
|
||
<RequestedBy>Someone</RequestedBy>
|
||
</payload>";
|
||
|
||
var xmlDocument = new XmlDocument();
|
||
|
||
xmlDocument.LoadXml(xml);
|
||
|
||
var result = xmlDocument.FirstChild.ChildNodes.Cast<XmlNode>().ToArray();
|
||
|
||
var json = JsonConvert.SerializeObject(result, Formatting.Indented); // <--- fails here with the cast message
|
||
|
||
StringAssert.AreEqual(@"[
|
||
{
|
||
""Country"": ""6""
|
||
},
|
||
{
|
||
""FinancialTransactionApprovalRequestUID"": ""79""
|
||
},
|
||
{
|
||
""TransactionStatus"": ""Approved""
|
||
},
|
||
{
|
||
""StatusChangeComment"": """"
|
||
},
|
||
{
|
||
""RequestedBy"": ""Someone""
|
||
}
|
||
]", json);
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void SerializeXElement()
|
||
{
|
||
string xml = @"<payload>
|
||
<Country>6</Country>
|
||
<FinancialTransactionApprovalRequestUID>79</FinancialTransactionApprovalRequestUID>
|
||
<TransactionStatus>Approved</TransactionStatus>
|
||
<StatusChangeComment></StatusChangeComment>
|
||
<RequestedBy>Someone</RequestedBy>
|
||
</payload>";
|
||
|
||
var xmlDocument = XDocument.Parse(xml);
|
||
|
||
var result = xmlDocument.Root.Nodes().ToArray();
|
||
|
||
var json = JsonConvert.SerializeObject(result, Formatting.Indented); // <--- fails here with the cast message
|
||
|
||
StringAssert.AreEqual(@"[
|
||
{
|
||
""Country"": ""6""
|
||
},
|
||
{
|
||
""FinancialTransactionApprovalRequestUID"": ""79""
|
||
},
|
||
{
|
||
""TransactionStatus"": ""Approved""
|
||
},
|
||
{
|
||
""StatusChangeComment"": """"
|
||
},
|
||
{
|
||
""RequestedBy"": ""Someone""
|
||
}
|
||
]", json);
|
||
}
|
||
|
||
public class DecimalContainer
|
||
{
|
||
public decimal Number { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void FloatParseHandlingDecimal()
|
||
{
|
||
decimal d = (decimal)Math.PI + 1000000000m;
|
||
var x = new DecimalContainer { Number = d };
|
||
|
||
var json = JsonConvert.SerializeObject(x, Formatting.Indented);
|
||
|
||
XDocument doc1 = JsonConvert.DeserializeObject<XDocument>(json, new JsonSerializerSettings
|
||
{
|
||
Converters = { new XmlNodeConverter() },
|
||
FloatParseHandling = FloatParseHandling.Decimal
|
||
});
|
||
|
||
var xml = doc1.ToString();
|
||
Assert.AreEqual("<Number>1000000003.14159265358979</Number>", xml);
|
||
|
||
string json2 = JsonConvert.SerializeObject(doc1, Formatting.Indented);
|
||
|
||
DecimalContainer x2 = JsonConvert.DeserializeObject<DecimalContainer>(json2);
|
||
|
||
Assert.AreEqual(x.Number, x2.Number);
|
||
}
|
||
|
||
public class DateTimeOffsetContainer
|
||
{
|
||
public DateTimeOffset Date { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeParseHandlingOffset()
|
||
{
|
||
DateTimeOffset d = new DateTimeOffset(2012, 12, 12, 12, 44, 1, TimeSpan.FromHours(12).Add(TimeSpan.FromMinutes(34)));
|
||
var x = new DateTimeOffsetContainer { Date = d };
|
||
|
||
var json = JsonConvert.SerializeObject(x, Formatting.Indented);
|
||
|
||
XDocument doc1 = JsonConvert.DeserializeObject<XDocument>(json, new JsonSerializerSettings
|
||
{
|
||
Converters = { new XmlNodeConverter() },
|
||
DateParseHandling = DateParseHandling.DateTimeOffset
|
||
});
|
||
|
||
var xml = doc1.ToString();
|
||
Assert.AreEqual("<Date>2012-12-12T12:44:01+12:34</Date>", xml);
|
||
|
||
string json2 = JsonConvert.SerializeObject(doc1, Formatting.Indented);
|
||
|
||
DateTimeOffsetContainer x2 = JsonConvert.DeserializeObject<DateTimeOffsetContainer>(json2);
|
||
|
||
Assert.AreEqual(x.Date, x2.Date);
|
||
}
|
||
|
||
[Test]
|
||
public void GroupElementsOfTheSameName()
|
||
{
|
||
string xml = "<root><p>Text1<span>Span1</span> <span>Span2</span> Text2</p></root>";
|
||
|
||
string json = JsonConvert.SerializeXNode(XElement.Parse(xml));
|
||
|
||
Assert.AreEqual(@"{""root"":{""p"":{""#text"":[""Text1"","" Text2""],""span"":[""Span1"",""Span2""]}}}", json);
|
||
|
||
XDocument doc = JsonConvert.DeserializeXNode(json);
|
||
|
||
StringAssert.AreEqual(@"<root>
|
||
<p>Text1 Text2<span>Span1</span><span>Span2</span></p>
|
||
</root>", doc.ToString());
|
||
}
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void SerializeEmptyDocument()
|
||
{
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml("<root />");
|
||
|
||
string json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true);
|
||
Assert.AreEqual("null", json);
|
||
|
||
doc = new XmlDocument();
|
||
doc.LoadXml("<root></root>");
|
||
|
||
json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true);
|
||
Assert.AreEqual(@"""""", json);
|
||
|
||
XDocument doc1 = XDocument.Parse("<root />");
|
||
|
||
json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true);
|
||
Assert.AreEqual("null", json);
|
||
|
||
doc1 = XDocument.Parse("<root></root>");
|
||
|
||
json = JsonConvert.SerializeXNode(doc1, Formatting.Indented, true);
|
||
Assert.AreEqual(@"""""", json);
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void SerializeAndDeserializeXmlWithNamespaceInChildrenAndNoValueInChildren()
|
||
{
|
||
var xmlString = @"<root>
|
||
<b xmlns='http://www.example.com/ns'/>
|
||
<c>AAA</c>
|
||
<test>adad</test>
|
||
</root>";
|
||
|
||
var xml = XElement.Parse(xmlString);
|
||
|
||
var json1 = JsonConvert.SerializeXNode(xml);
|
||
var xmlBack = JsonConvert.DeserializeObject<XElement>(json1);
|
||
|
||
var equals = XElement.DeepEquals(xmlBack, xml);
|
||
Assert.IsTrue(equals);
|
||
}
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void DeserializeUndeclaredNamespacePrefix()
|
||
{
|
||
XmlDocument doc = JsonConvert.DeserializeXmlNode("{ A: { '@xsi:nil': true } }");
|
||
|
||
Assert.AreEqual(@"<A nil=""true"" />", doc.OuterXml);
|
||
|
||
XDocument xdoc = JsonConvert.DeserializeXNode("{ A: { '@xsi:nil': true } }");
|
||
|
||
Assert.AreEqual(doc.OuterXml, xdoc.ToString());
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void DeserializeMultipleRootElements()
|
||
{
|
||
string json = @"{
|
||
""Id"": 1,
|
||
""Email"": ""james@example.com"",
|
||
""Active"": true,
|
||
""CreatedDate"": ""2013-01-20T00:00:00Z"",
|
||
""Roles"": [
|
||
""User"",
|
||
""Admin""
|
||
],
|
||
""Team"": {
|
||
""Id"": 2,
|
||
""Name"": ""Software Developers"",
|
||
""Description"": ""Creators of fine software products and services.""
|
||
}
|
||
}";
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { JsonConvert.DeserializeXmlNode(json); },
|
||
"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.");
|
||
}
|
||
|
||
[Test]
|
||
public void DocumentSerializeIndented()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||
<?xml-stylesheet href=""classic.xsl"" type=""text/xml""?>
|
||
<span class=""vevent"">
|
||
<a class=""url"" href=""http://www.web2con.com/"">
|
||
<span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
|
||
<abbr class=""dtstart"" title=""2005-10-05"">October 5</abbr>
|
||
<abbr class=""dtend"" title=""2005-10-08"">7</abbr>
|
||
<span class=""location"">Argent Hotel, San Francisco, CA</span>
|
||
</a>
|
||
</span>";
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
string expected = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""span"": {
|
||
""@class"": ""vevent"",
|
||
""a"": {
|
||
""@class"": ""url"",
|
||
""@href"": ""http://www.web2con.com/"",
|
||
""span"": [
|
||
{
|
||
""@class"": ""summary"",
|
||
""#text"": ""Web 2.0 Conference"",
|
||
""#cdata-section"": ""my escaped text""
|
||
},
|
||
{
|
||
""@class"": ""location"",
|
||
""#text"": ""Argent Hotel, San Francisco, CA""
|
||
}
|
||
],
|
||
""abbr"": [
|
||
{
|
||
""@class"": ""dtstart"",
|
||
""@title"": ""2005-10-05"",
|
||
""#text"": ""October 5""
|
||
},
|
||
{
|
||
""@class"": ""dtend"",
|
||
""@title"": ""2005-10-08"",
|
||
""#text"": ""7""
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expected, jsonText);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeNodeTypes()
|
||
{
|
||
XmlDocument doc = new XmlDocument();
|
||
string jsonText;
|
||
|
||
string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
|
||
<xs:schema xs:id=""SomeID""
|
||
xmlns=""""
|
||
xmlns:xs=""http://www.w3.org/2001/XMLSchema""
|
||
xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
|
||
<xs:element name=""MyDataSet"" msdata:IsDataSet=""true"">
|
||
</xs:element>
|
||
</xs:schema>";
|
||
|
||
XmlDocument document = new XmlDocument();
|
||
document.LoadXml(xml);
|
||
|
||
// XmlAttribute
|
||
XmlAttribute attribute = document.DocumentElement.ChildNodes[0].Attributes["IsDataSet", "urn:schemas-microsoft-com:xml-msdata"];
|
||
attribute.Value = "true";
|
||
|
||
jsonText = JsonConvert.SerializeXmlNode(attribute);
|
||
|
||
Assert.AreEqual(@"{""@msdata:IsDataSet"":""true""}", jsonText);
|
||
|
||
#if !NET20
|
||
XDocument d = XDocument.Parse(xml);
|
||
XAttribute a = d.Root.Element("{http://www.w3.org/2001/XMLSchema}element").Attribute("{urn:schemas-microsoft-com:xml-msdata}IsDataSet");
|
||
|
||
jsonText = JsonConvert.SerializeXNode(a);
|
||
|
||
Assert.AreEqual(@"{""@msdata:IsDataSet"":""true""}", jsonText);
|
||
#endif
|
||
|
||
// XmlProcessingInstruction
|
||
XmlProcessingInstruction instruction = doc.CreateProcessingInstruction("xml-stylesheet", @"href=""classic.xsl"" type=""text/xml""");
|
||
|
||
jsonText = JsonConvert.SerializeXmlNode(instruction);
|
||
|
||
Assert.AreEqual(@"{""?xml-stylesheet"":""href=\""classic.xsl\"" type=\""text/xml\""""}", jsonText);
|
||
|
||
// XmlProcessingInstruction
|
||
XmlCDataSection cDataSection = doc.CreateCDataSection("<Kiwi>true</Kiwi>");
|
||
|
||
jsonText = JsonConvert.SerializeXmlNode(cDataSection);
|
||
|
||
Assert.AreEqual(@"{""#cdata-section"":""<Kiwi>true</Kiwi>""}", jsonText);
|
||
|
||
// XmlElement
|
||
XmlElement element = doc.CreateElement("xs", "Choice", "http://www.w3.org/2001/XMLSchema");
|
||
element.SetAttributeNode(doc.CreateAttribute("msdata", "IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));
|
||
|
||
XmlAttribute aa = doc.CreateAttribute(@"xmlns", "xs", "http://www.w3.org/2000/xmlns/");
|
||
aa.Value = "http://www.w3.org/2001/XMLSchema";
|
||
element.SetAttributeNode(aa);
|
||
|
||
aa = doc.CreateAttribute(@"xmlns", "msdata", "http://www.w3.org/2000/xmlns/");
|
||
aa.Value = "urn:schemas-microsoft-com:xml-msdata";
|
||
element.SetAttributeNode(aa);
|
||
|
||
element.AppendChild(instruction);
|
||
element.AppendChild(cDataSection);
|
||
|
||
doc.AppendChild(element);
|
||
|
||
jsonText = JsonConvert.SerializeXmlNode(element, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""xs:Choice"": {
|
||
""@msdata:IsDataSet"": """",
|
||
""@xmlns:xs"": ""http://www.w3.org/2001/XMLSchema"",
|
||
""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""#cdata-section"": ""<Kiwi>true</Kiwi>""
|
||
}
|
||
}", jsonText);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeNodeTypes_Encoding()
|
||
{
|
||
XmlNode node = DeserializeXmlNode(@"{
|
||
""xs!:Choice!"": {
|
||
""@msdata:IsDataSet!"": """",
|
||
""@xmlns:xs!"": ""http://www.w3.org/2001/XMLSchema"",
|
||
""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""#cdata-section"": ""<Kiwi>true</Kiwi>""
|
||
}
|
||
}");
|
||
|
||
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);
|
||
|
||
string json = SerializeXmlNode(node);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""xs!:Choice!"": {
|
||
""@msdata:IsDataSet!"": """",
|
||
""@xmlns:xs!"": ""http://www.w3.org/2001/XMLSchema"",
|
||
""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
|
||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||
""#cdata-section"": ""<Kiwi>true</Kiwi>""
|
||
}
|
||
}", json);
|
||
}
|
||
|
||
[Test]
|
||
public void DocumentFragmentSerialize()
|
||
{
|
||
XmlDocument doc = new XmlDocument();
|
||
|
||
XmlDocumentFragment fragement = doc.CreateDocumentFragment();
|
||
|
||
fragement.InnerXml = "<Item>widget</Item><Item>widget</Item>";
|
||
|
||
string jsonText = JsonConvert.SerializeXmlNode(fragement);
|
||
|
||
string expected = @"{""Item"":[""widget"",""widget""]}";
|
||
|
||
Assert.AreEqual(expected, jsonText);
|
||
}
|
||
|
||
#if !NETSTANDARD1_3
|
||
[Test]
|
||
public void XmlDocumentTypeSerialize()
|
||
{
|
||
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>";
|
||
|
||
string expected = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@encoding"": ""utf-8""
|
||
},
|
||
""!DOCTYPE"": {
|
||
""@name"": ""STOCKQUOTE"",
|
||
""@public"": ""-//W3C//DTD StockQuote 1.5//EN"",
|
||
""@system"": ""http://www.idontexistnopenopewhatnope123.org/dtd/stockquote_1.5.dtd""
|
||
},
|
||
""STOCKQUOTE"": {
|
||
""@ROWCOUNT"": ""2"",
|
||
""RESULT"": {
|
||
""ROW"": [
|
||
{
|
||
""ASK"": ""0"",
|
||
""BID"": ""0"",
|
||
""CHANGE"": ""-16.310"",
|
||
""COMPANYNAME"": ""Dow Jones"",
|
||
""DATETIME"": ""2014-04-17 15:50:37"",
|
||
""DIVIDEND"": ""0"",
|
||
""EPS"": ""0"",
|
||
""EXCHANGE"": """",
|
||
""HIGH"": ""16460.490"",
|
||
""LASTDATETIME"": ""2014-04-17 15:50:37"",
|
||
""LASTPRICE"": ""16408.540"",
|
||
""LOW"": ""16368.140"",
|
||
""OPEN"": ""16424.140"",
|
||
""PCHANGE"": ""-0.099"",
|
||
""PE"": ""0"",
|
||
""PREVIOUSCLOSE"": ""16424.850"",
|
||
""SHARES"": ""0"",
|
||
""TICKER"": ""DJII"",
|
||
""TRADES"": ""0"",
|
||
""VOLUME"": ""136188700"",
|
||
""YEARHIGH"": ""11309.000"",
|
||
""YEARLOW"": ""9302.280"",
|
||
""YIELD"": ""0""
|
||
},
|
||
{
|
||
""ASK"": ""0"",
|
||
""BID"": ""0"",
|
||
""CHANGE"": ""9.290"",
|
||
""COMPANYNAME"": ""NASDAQ"",
|
||
""DATETIME"": ""2014-04-17 15:40:01"",
|
||
""DIVIDEND"": ""0"",
|
||
""EPS"": ""0"",
|
||
""EXCHANGE"": """",
|
||
""HIGH"": ""4110.460"",
|
||
""LASTDATETIME"": ""2014-04-17 15:40:01"",
|
||
""LASTPRICE"": ""4095.520"",
|
||
""LOW"": ""4064.700"",
|
||
""OPEN"": ""4080.300"",
|
||
""PCHANGE"": ""0.227"",
|
||
""PE"": ""0"",
|
||
""PREVIOUSCLOSE"": ""4086.230"",
|
||
""SHARES"": ""0"",
|
||
""TICKER"": ""COMP"",
|
||
""TRADES"": ""0"",
|
||
""VOLUME"": ""1784210100"",
|
||
""YEARHIGH"": ""4371.710"",
|
||
""YEARLOW"": ""3154.960"",
|
||
""YIELD"": ""0""
|
||
}
|
||
]
|
||
},
|
||
""STATUS"": ""Couldn't find ticker: SPIC?"",
|
||
""STATUSCODE"": ""2""
|
||
}
|
||
}";
|
||
|
||
XmlDocument doc1 = new XmlDocument();
|
||
doc1.XmlResolver = null;
|
||
doc1.LoadXml(xml);
|
||
|
||
string json1 = JsonConvert.SerializeXmlNode(doc1, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(expected, json1);
|
||
|
||
XmlDocument doc11 = JsonConvert.DeserializeXmlNode(json1);
|
||
|
||
StringAssert.AreEqual(xml, ToStringWithDeclaration(doc11));
|
||
|
||
#if !NET20
|
||
XDocument doc2 = XDocument.Parse(xml);
|
||
|
||
string json2 = JsonConvert.SerializeXNode(doc2, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(expected, json2);
|
||
|
||
XDocument doc22 = JsonConvert.DeserializeXNode(json2);
|
||
|
||
StringAssert.AreEqual(xml, ToStringWithDeclaration(doc22));
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
public class Utf8StringWriter : StringWriter
|
||
{
|
||
public override Encoding Encoding
|
||
{
|
||
get { return Encoding.UTF8; }
|
||
}
|
||
|
||
public Utf8StringWriter(StringBuilder sb) : base(sb)
|
||
{
|
||
}
|
||
}
|
||
|
||
#if !NET20
|
||
public static string ToStringWithDeclaration(XDocument doc, bool indent = false)
|
||
{
|
||
StringBuilder builder = new StringBuilder();
|
||
using (var writer = XmlWriter.Create(new Utf8StringWriter(builder), new XmlWriterSettings { Indent = indent }))
|
||
{
|
||
doc.Save(writer);
|
||
}
|
||
return builder.ToString();
|
||
}
|
||
#endif
|
||
|
||
public static string ToStringWithDeclaration(XmlDocument doc, bool indent = false)
|
||
{
|
||
StringBuilder builder = new StringBuilder();
|
||
using (var writer = XmlWriter.Create(new Utf8StringWriter(builder), new XmlWriterSettings { Indent = indent }))
|
||
{
|
||
doc.Save(writer);
|
||
}
|
||
return builder.ToString();
|
||
}
|
||
|
||
[Test]
|
||
public void NamespaceSerializeDeserialize()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
|
||
<xs:schema xs:id=""SomeID""
|
||
xmlns=""""
|
||
xmlns:xs=""http://www.w3.org/2001/XMLSchema""
|
||
xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
|
||
<xs:element name=""MyDataSet"" msdata:IsDataSet=""true"">
|
||
<xs:complexType>
|
||
<xs:choice maxOccurs=""unbounded"">
|
||
<xs:element name=""customers"" >
|
||
<xs:complexType >
|
||
<xs:sequence>
|
||
<xs:element name=""CustomerID"" type=""xs:integer""
|
||
minOccurs=""0"" />
|
||
<xs:element name=""CompanyName"" type=""xs:string""
|
||
minOccurs=""0"" />
|
||
<xs:element name=""Phone"" type=""xs:string"" />
|
||
</xs:sequence>
|
||
</xs:complexType>
|
||
</xs:element>
|
||
</xs:choice>
|
||
</xs:complexType>
|
||
</xs:element>
|
||
</xs:schema>";
|
||
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
|
||
string expected = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@encoding"": ""utf-8""
|
||
},
|
||
""xs:schema"": {
|
||
""@xs:id"": ""SomeID"",
|
||
""@xmlns"": """",
|
||
""@xmlns:xs"": ""http://www.w3.org/2001/XMLSchema"",
|
||
""@xmlns:msdata"": ""urn:schemas-microsoft-com:xml-msdata"",
|
||
""xs:element"": {
|
||
""@name"": ""MyDataSet"",
|
||
""@msdata:IsDataSet"": ""true"",
|
||
""xs:complexType"": {
|
||
""xs:choice"": {
|
||
""@maxOccurs"": ""unbounded"",
|
||
""xs:element"": {
|
||
""@name"": ""customers"",
|
||
""xs:complexType"": {
|
||
""xs:sequence"": {
|
||
""xs:element"": [
|
||
{
|
||
""@name"": ""CustomerID"",
|
||
""@type"": ""xs:integer"",
|
||
""@minOccurs"": ""0""
|
||
},
|
||
{
|
||
""@name"": ""CompanyName"",
|
||
""@type"": ""xs:string"",
|
||
""@minOccurs"": ""0""
|
||
},
|
||
{
|
||
""@name"": ""Phone"",
|
||
""@type"": ""xs:string""
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expected, jsonText);
|
||
|
||
XmlDocument deserializedDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
Assert.AreEqual(doc.InnerXml, deserializedDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void FailOnIncomplete()
|
||
{
|
||
string json = @"{'Row' : ";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => JsonConvert.DeserializeXmlNode(json, "ROOT"),
|
||
"Unexpected end when reading JSON. Path 'Row', line 1, position 9.");
|
||
}
|
||
|
||
[Test]
|
||
public void DocumentDeserialize()
|
||
{
|
||
string jsonText = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""span"": {
|
||
""@class"": ""vevent"",
|
||
""a"": {
|
||
""@class"": ""url"",
|
||
""span"": {
|
||
""@class"": ""summary"",
|
||
""#text"": ""Web 2.0 Conference"",
|
||
""#cdata-section"": ""my escaped text""
|
||
},
|
||
""@href"": ""http://www.web2con.com/""
|
||
}
|
||
}
|
||
}";
|
||
|
||
XmlDocument doc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
string expected = @"<?xml version=""1.0"" standalone=""no""?>
|
||
<span class=""vevent"">
|
||
<a class=""url"" href=""http://www.web2con.com/"">
|
||
<span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
|
||
</a>
|
||
</span>";
|
||
|
||
string formattedXml = GetIndentedInnerXml(doc);
|
||
|
||
StringAssert.AreEqual(expected, formattedXml);
|
||
}
|
||
|
||
private string GetIndentedInnerXml(XmlNode node)
|
||
{
|
||
XmlWriterSettings settings = new XmlWriterSettings();
|
||
settings.Indent = true;
|
||
|
||
StringWriter sw = new StringWriter();
|
||
|
||
using (XmlWriter writer = XmlWriter.Create(sw, settings))
|
||
{
|
||
node.WriteTo(writer);
|
||
}
|
||
|
||
return sw.ToString();
|
||
}
|
||
|
||
public class Foo2
|
||
{
|
||
public XmlElement Bar { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeAndDeserializeXmlElement()
|
||
{
|
||
Foo2 foo = new Foo2 { Bar = null };
|
||
string json = JsonConvert.SerializeObject(foo);
|
||
|
||
Assert.AreEqual(@"{""Bar"":null}", json);
|
||
Foo2 foo2 = JsonConvert.DeserializeObject<Foo2>(json);
|
||
|
||
Assert.IsNull(foo2.Bar);
|
||
}
|
||
|
||
[Test]
|
||
public void SingleTextNode()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||
<root>
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
</person>
|
||
<person id=""2"">
|
||
<name>Louis</name>
|
||
<url>http://www.yahoo.com</url>
|
||
</person>
|
||
</root>";
|
||
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void EmptyNode()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||
<root>
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url />
|
||
</person>
|
||
<person id=""2"">
|
||
<name>Louis</name>
|
||
<url>http://www.yahoo.com</url>
|
||
</person>
|
||
</root>";
|
||
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""root"": {
|
||
""person"": [
|
||
{
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": null
|
||
},
|
||
{
|
||
""@id"": ""2"",
|
||
""name"": ""Louis"",
|
||
""url"": ""http://www.yahoo.com""
|
||
}
|
||
]
|
||
}
|
||
}", jsonText);
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void OtherElementDataTypes()
|
||
{
|
||
string jsonText = @"{""?xml"":{""@version"":""1.0"",""@standalone"":""no""},""root"":{""person"":[{""@id"":""1"",""Float"":2.5,""Integer"":99},{""Boolean"":true,""@id"":""2"",""date"":""\/Date(954374400000)\/""}]}}";
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
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>";
|
||
|
||
Assert.AreEqual(expected, newDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void NoRootObject()
|
||
{
|
||
ExceptionAssert.Throws<JsonSerializationException>(() => { XmlDocument newDoc = (XmlDocument)JsonConvert.DeserializeXmlNode(@"[1]"); }, "XmlNodeConverter can only convert JSON that begins with an object. Path '', line 1, position 1.");
|
||
}
|
||
|
||
[Test]
|
||
public void RootObjectMultipleProperties()
|
||
{
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { XmlDocument newDoc = (XmlDocument)JsonConvert.DeserializeXmlNode(@"{Prop1:1,Prop2:2}"); },
|
||
"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.");
|
||
}
|
||
|
||
[Test]
|
||
public void JavaScriptConstructor()
|
||
{
|
||
string jsonText = @"{root:{r:new Date(34343, 55)}}";
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
string expected = @"<root><r><Date>34343</Date><Date>55</Date></r></root>";
|
||
|
||
Assert.AreEqual(expected, newDoc.InnerXml);
|
||
|
||
string json = SerializeXmlNode(newDoc);
|
||
expected = @"{
|
||
""root"": {
|
||
""r"": {
|
||
""Date"": [
|
||
""34343"",
|
||
""55""
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expected, json);
|
||
}
|
||
|
||
[Test]
|
||
public void ForceJsonArray()
|
||
{
|
||
string arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
<role json:Array=""true"">Admin</role>
|
||
</person>
|
||
</root>";
|
||
|
||
XmlDocument arrayDoc = new XmlDocument();
|
||
arrayDoc.LoadXml(arrayXml);
|
||
|
||
string arrayJsonText = SerializeXmlNode(arrayDoc);
|
||
string expected = @"{
|
||
""root"": {
|
||
""person"": {
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com"",
|
||
""role"": [
|
||
""Admin""
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
StringAssert.AreEqual(expected, arrayJsonText);
|
||
|
||
arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
<role json:Array=""true"">Admin1</role>
|
||
<role json:Array=""true"">Admin2</role>
|
||
</person>
|
||
</root>";
|
||
|
||
arrayDoc = new XmlDocument();
|
||
arrayDoc.LoadXml(arrayXml);
|
||
|
||
arrayJsonText = SerializeXmlNode(arrayDoc);
|
||
expected = @"{
|
||
""root"": {
|
||
""person"": {
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com"",
|
||
""role"": [
|
||
""Admin1"",
|
||
""Admin2""
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
StringAssert.AreEqual(expected, arrayJsonText);
|
||
|
||
arrayXml = @"<root xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
<role json:Array=""false"">Admin1</role>
|
||
</person>
|
||
</root>";
|
||
|
||
arrayDoc = new XmlDocument();
|
||
arrayDoc.LoadXml(arrayXml);
|
||
|
||
arrayJsonText = SerializeXmlNode(arrayDoc);
|
||
expected = @"{
|
||
""root"": {
|
||
""person"": {
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com"",
|
||
""role"": ""Admin1""
|
||
}
|
||
}
|
||
}";
|
||
StringAssert.AreEqual(expected, arrayJsonText);
|
||
|
||
arrayXml = @"<root>
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
<role json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">Admin</role>
|
||
</person>
|
||
</root>";
|
||
|
||
arrayDoc = new XmlDocument();
|
||
arrayDoc.LoadXml(arrayXml);
|
||
|
||
arrayJsonText = SerializeXmlNode(arrayDoc);
|
||
expected = @"{
|
||
""root"": {
|
||
""person"": {
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com"",
|
||
""role"": [
|
||
""Admin""
|
||
]
|
||
}
|
||
}
|
||
}";
|
||
StringAssert.AreEqual(expected, arrayJsonText);
|
||
}
|
||
|
||
[Test]
|
||
public void MultipleRootPropertiesXmlDocument()
|
||
{
|
||
string json = @"{""count"": 773840,""photos"": null}";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { JsonConvert.DeserializeXmlNode(json); },
|
||
"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.");
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void MultipleRootPropertiesXDocument()
|
||
{
|
||
string json = @"{""count"": 773840,""photos"": null}";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { JsonConvert.DeserializeXNode(json); },
|
||
"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.");
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void MultipleRootPropertiesAddRootElement()
|
||
{
|
||
string json = @"{""count"": 773840,""photos"": 773840}";
|
||
|
||
#if !PORTABLE
|
||
XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
|
||
|
||
Assert.AreEqual(@"<myRoot><count>773840</count><photos>773840</photos></myRoot>", newDoc.InnerXml);
|
||
#endif
|
||
|
||
#if !NET20
|
||
XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
|
||
|
||
Assert.AreEqual(@"<myRoot><count>773840</count><photos>773840</photos></myRoot>", newXDoc.ToString(SaveOptions.DisableFormatting));
|
||
#endif
|
||
}
|
||
|
||
[Test]
|
||
public void NestedArrays()
|
||
{
|
||
string json = @"{
|
||
""available_sizes"": [
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-150x150.jpg"",
|
||
""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
|
||
],
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg"",
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
|
||
],
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
|
||
]
|
||
]
|
||
}";
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
|
||
|
||
string xml = IndentXml(newDoc.InnerXml);
|
||
|
||
StringAssert.AreEqual(@"<myRoot>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
</myRoot>", IndentXml(newDoc.InnerXml));
|
||
#endif
|
||
|
||
#if !NET20
|
||
XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
|
||
|
||
StringAssert.AreEqual(@"<myRoot>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
</myRoot>", IndentXml(newXDoc.ToString(SaveOptions.DisableFormatting)));
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented);
|
||
Console.WriteLine(newJson);
|
||
#endif
|
||
}
|
||
|
||
[Test]
|
||
public void RoundTripNestedArrays()
|
||
{
|
||
string json = @"{
|
||
""available_sizes"": [
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-150x150.jpg"",
|
||
""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
|
||
],
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg"",
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
|
||
],
|
||
[
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
|
||
]
|
||
]
|
||
}";
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot", true);
|
||
|
||
StringAssert.AreEqual(@"<myRoot>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes json:Array=""true"">assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
</myRoot>", IndentXml(newDoc.InnerXml));
|
||
#endif
|
||
|
||
#if !NET20
|
||
XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot", true);
|
||
|
||
StringAssert.AreEqual(@"<myRoot>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-150x150.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
<available_sizes>assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
<available_sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<available_sizes json:Array=""true"">assets/images/resized/0001/1070/11070v1-max-250x250.jpg</available_sizes>
|
||
</available_sizes>
|
||
</myRoot>", IndentXml(newXDoc.ToString(SaveOptions.DisableFormatting)));
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented, true);
|
||
StringAssert.AreEqual(json, newJson);
|
||
#endif
|
||
}
|
||
|
||
[Test]
|
||
public void MultipleNestedArraysToXml()
|
||
{
|
||
string json = @"{
|
||
""available_sizes"": [
|
||
[
|
||
[113, 150],
|
||
""assets/images/resized/0001/1070/11070v1-max-150x150.jpg""
|
||
],
|
||
[
|
||
[189, 250],
|
||
""assets/images/resized/0001/1070/11070v1-max-250x250.jpg""
|
||
],
|
||
[
|
||
[341, 450],
|
||
""assets/images/resized/0001/1070/11070v1-max-450x450.jpg""
|
||
]
|
||
]
|
||
}";
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
|
||
|
||
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);
|
||
#endif
|
||
|
||
#if !NET20
|
||
XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
|
||
|
||
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));
|
||
#endif
|
||
}
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void Encoding()
|
||
{
|
||
XmlDocument doc = new XmlDocument();
|
||
|
||
doc.LoadXml(@"<name>O""Connor</name>"); // i use "" so it will be easier to see the problem
|
||
|
||
string json = SerializeXmlNode(doc);
|
||
StringAssert.AreEqual(@"{
|
||
""name"": ""O\""Connor""
|
||
}", json);
|
||
}
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void SerializeComment()
|
||
{
|
||
string xml = @"<span class=""vevent"">
|
||
<a class=""url"" href=""http://www.web2con.com/""><!-- Hi --><span>Text</span></a><!-- Hi! -->
|
||
</span>";
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
|
||
string expected = @"{
|
||
""span"": {
|
||
""@class"": ""vevent"",
|
||
""a"": {
|
||
""@class"": ""url"",
|
||
""@href"": ""http://www.web2con.com/""/* Hi */,
|
||
""span"": ""Text""
|
||
}/* Hi! */
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expected, jsonText);
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
Assert.AreEqual(@"<span class=""vevent""><a class=""url"" href=""http://www.web2con.com/""><!-- Hi --><span>Text</span></a><!-- Hi! --></span>", newDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeExample()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||
<root>
|
||
<person id=""1"">
|
||
<name>Alan</name>
|
||
<url>http://www.google.com</url>
|
||
</person>
|
||
<person id=""2"">
|
||
<name>Louis</name>
|
||
<url>http://www.yahoo.com</url>
|
||
</person>
|
||
</root>";
|
||
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.LoadXml(xml);
|
||
|
||
string jsonText = SerializeXmlNode(doc);
|
||
// {
|
||
// "?xml": {
|
||
// "@version": "1.0",
|
||
// "@standalone": "no"
|
||
// },
|
||
// "root": {
|
||
// "person": [
|
||
// {
|
||
// "@id": "1",
|
||
// "name": "Alan",
|
||
// "url": "http://www.google.com"
|
||
// },
|
||
// {
|
||
// "@id": "2",
|
||
// "name": "Louis",
|
||
// "url": "http://www.yahoo.com"
|
||
// }
|
||
// ]
|
||
// }
|
||
// }
|
||
|
||
// format
|
||
jsonText = JObject.Parse(jsonText).ToString();
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""root"": {
|
||
""person"": [
|
||
{
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com""
|
||
},
|
||
{
|
||
""@id"": ""2"",
|
||
""name"": ""Louis"",
|
||
""url"": ""http://www.yahoo.com""
|
||
}
|
||
]
|
||
}
|
||
}", jsonText);
|
||
|
||
XmlDocument newDoc = (XmlDocument)DeserializeXmlNode(jsonText);
|
||
|
||
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void DeserializeExample()
|
||
{
|
||
string json = @"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@standalone"": ""no""
|
||
},
|
||
""root"": {
|
||
""person"": [
|
||
{
|
||
""@id"": ""1"",
|
||
""name"": ""Alan"",
|
||
""url"": ""http://www.google.com""
|
||
},
|
||
{
|
||
""@id"": ""2"",
|
||
""name"": ""Louis"",
|
||
""url"": ""http://www.yahoo.com""
|
||
}
|
||
]
|
||
}
|
||
}";
|
||
|
||
XmlDocument doc = (XmlDocument)DeserializeXmlNode(json);
|
||
// <?xml version="1.0" standalone="no"?>
|
||
// <root>
|
||
// <person id="1">
|
||
// <name>Alan</name>
|
||
// <url>http://www.google.com</url>
|
||
// </person>
|
||
// <person id="2">
|
||
// <name>Louis</name>
|
||
// <url>http://www.yahoo.com</url>
|
||
// </person>
|
||
// </root>
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" standalone=""no""?><root><person id=""1""><name>Alan</name><url>http://www.google.com</url></person><person id=""2""><name>Louis</name><url>http://www.yahoo.com</url></person></root>", doc.InnerXml);
|
||
}
|
||
|
||
[Test]
|
||
public void EscapingNames()
|
||
{
|
||
string json = @"{
|
||
""root!"": {
|
||
""person!"": [
|
||
{
|
||
""@id!"": ""1"",
|
||
""name!"": ""Alan"",
|
||
""url!"": ""http://www.google.com""
|
||
},
|
||
{
|
||
""@id!"": ""2"",
|
||
""name!"": ""Louis"",
|
||
""url!"": ""http://www.yahoo.com""
|
||
}
|
||
]
|
||
}
|
||
}";
|
||
|
||
XmlDocument doc = (XmlDocument)DeserializeXmlNode(json);
|
||
|
||
Assert.AreEqual(@"<root_x0021_><person_x0021_ id_x0021_=""1""><name_x0021_>Alan</name_x0021_><url_x0021_>http://www.google.com</url_x0021_></person_x0021_><person_x0021_ id_x0021_=""2""><name_x0021_>Louis</name_x0021_><url_x0021_>http://www.yahoo.com</url_x0021_></person_x0021_></root_x0021_>", doc.InnerXml);
|
||
|
||
string json2 = SerializeXmlNode(doc);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""root!"": {
|
||
""person!"": [
|
||
{
|
||
""@id!"": ""1"",
|
||
""name!"": ""Alan"",
|
||
""url!"": ""http://www.google.com""
|
||
},
|
||
{
|
||
""@id!"": ""2"",
|
||
""name!"": ""Louis"",
|
||
""url!"": ""http://www.yahoo.com""
|
||
}
|
||
]
|
||
}
|
||
}", json2);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataProperties()
|
||
{
|
||
PreserveReferencesHandlingTests.CircularDictionary circularDictionary = new PreserveReferencesHandlingTests.CircularDictionary();
|
||
circularDictionary.Add("other", new PreserveReferencesHandlingTests.CircularDictionary { { "blah", null } });
|
||
circularDictionary.Add("self", circularDictionary);
|
||
|
||
string json = JsonConvert.SerializeObject(circularDictionary, Formatting.Indented,
|
||
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""$id"": ""1"",
|
||
""other"": {
|
||
""$id"": ""2"",
|
||
""blah"": null
|
||
},
|
||
""self"": {
|
||
""$ref"": ""1""
|
||
}
|
||
}", json);
|
||
|
||
XmlNode node = DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
string expected = @"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"" json:id=""1"">
|
||
<other json:id=""2"">
|
||
<blah />
|
||
</other>
|
||
<self json:ref=""1"" />
|
||
</root>";
|
||
|
||
StringAssert.AreEqual(expected, xml);
|
||
|
||
string xmlJson = SerializeXmlNode(node);
|
||
string expectedXmlJson = @"{
|
||
""root"": {
|
||
""$id"": ""1"",
|
||
""other"": {
|
||
""$id"": ""2"",
|
||
""blah"": null
|
||
},
|
||
""self"": {
|
||
""$ref"": ""1""
|
||
}
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expectedXmlJson, xmlJson);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataArray()
|
||
{
|
||
string json = @"{
|
||
""$id"": ""1"",
|
||
""$values"": [
|
||
""1"",
|
||
""2"",
|
||
""3"",
|
||
""4"",
|
||
""5""
|
||
]
|
||
}";
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"" json:id=""1"">
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">1</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">2</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">3</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">4</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">5</values>
|
||
</root>", xml);
|
||
|
||
string newJson = JsonConvert.SerializeXmlNode(node, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(json, newJson);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataArrayNoId()
|
||
{
|
||
string json = @"{
|
||
""$values"": [
|
||
""1"",
|
||
""2"",
|
||
""3"",
|
||
""4"",
|
||
""5""
|
||
]
|
||
}";
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">1</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">2</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">3</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">4</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">5</values>
|
||
</root>", xml);
|
||
|
||
string newJson = JsonConvert.SerializeXmlNode(node, Formatting.Indented, true);
|
||
|
||
Console.WriteLine(newJson);
|
||
|
||
StringAssert.AreEqual(json, newJson);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataArrayWithIdLast()
|
||
{
|
||
string json = @"{
|
||
""$values"": [
|
||
""1"",
|
||
""2"",
|
||
""3"",
|
||
""4"",
|
||
""5""
|
||
],
|
||
""$id"": ""1""
|
||
}";
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"" json:id=""1"">
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">1</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">2</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">3</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">4</values>
|
||
<values xmlns=""http://james.newtonking.com/projects/json"">5</values>
|
||
</root>", xml);
|
||
|
||
string newJson = JsonConvert.SerializeXmlNode(node, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""$id"": ""1"",
|
||
""$values"": [
|
||
""1"",
|
||
""2"",
|
||
""3"",
|
||
""4"",
|
||
""5""
|
||
]
|
||
}", newJson);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeMetadataPropertyWithBadValue()
|
||
{
|
||
string json = @"{
|
||
""$id"": []
|
||
}";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { JsonConvert.DeserializeXmlNode(json, "root"); },
|
||
"Unexpected JsonToken: StartArray. Path '$id', line 2, position 10.");
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataWithNullValue()
|
||
{
|
||
string json = @"{
|
||
""$id"": null
|
||
}";
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"" json:id="""" />", xml);
|
||
|
||
string newJson = JsonConvert.SerializeXmlNode(node, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""$id"": """"
|
||
}", newJson);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDeserializeMetadataArrayNull()
|
||
{
|
||
string json = @"{
|
||
""$id"": ""1"",
|
||
""$values"": null
|
||
}";
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json, "root");
|
||
string xml = GetIndentedInnerXml(node);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-16""?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"" json:id=""1"">
|
||
<values xmlns=""http://james.newtonking.com/projects/json"" />
|
||
</root>", xml);
|
||
|
||
string newJson = JsonConvert.SerializeXmlNode(node, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(json, newJson);
|
||
}
|
||
|
||
[Test]
|
||
public void EmptyPropertyName()
|
||
{
|
||
string json = @"{
|
||
""8452309520V2"": {
|
||
"""": {
|
||
""CLIENT"": {
|
||
""ID_EXPIRATION_1"": {
|
||
""VALUE"": ""12/12/2000"",
|
||
""DATATYPE"": ""D"",
|
||
""MSG"": ""Missing Identification Exp. Date 1""
|
||
},
|
||
""ID_ISSUEDATE_1"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""D"",
|
||
""MSG"": ""Missing Identification Issue Date 1""
|
||
}
|
||
}
|
||
},
|
||
""457463534534"": {
|
||
""ACCOUNT"": {
|
||
""FUNDING_SOURCE"": {
|
||
""VALUE"": ""FS0"",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Source of Funds""
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}{
|
||
""34534634535345"": {
|
||
"""": {
|
||
""CLIENT"": {
|
||
""ID_NUMBER_1"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""S"",
|
||
""MSG"": ""Missing Picture ID""
|
||
},
|
||
""ID_EXPIRATION_1"": {
|
||
""VALUE"": ""12/12/2000"",
|
||
""DATATYPE"": ""D"",
|
||
""MSG"": ""Missing Picture ID""
|
||
},
|
||
""WALK_IN"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Walk in""
|
||
},
|
||
""PERSONAL_MEETING"": {
|
||
""VALUE"": ""PM1"",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Met Client in Person""
|
||
},
|
||
""ID_ISSUEDATE_1"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""D"",
|
||
""MSG"": ""Missing Picture ID""
|
||
},
|
||
""PHOTO_ID"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Picture ID""
|
||
},
|
||
""ID_TYPE_1"": {
|
||
""VALUE"": """",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Picture ID""
|
||
}
|
||
}
|
||
},
|
||
""45635624523"": {
|
||
""ACCOUNT"": {
|
||
""FUNDING_SOURCE"": {
|
||
""VALUE"": ""FS1"",
|
||
""DATATYPE"": ""L"",
|
||
""MSG"": ""Missing Source of Funds""
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => { DeserializeXmlNode(json); },
|
||
"XmlNodeConverter cannot convert JSON with an empty property name to XML. Path '8452309520V2.', line 3, position 9.");
|
||
}
|
||
|
||
[Test]
|
||
public void SingleItemArrayPropertySerialization()
|
||
{
|
||
Product product = new Product();
|
||
|
||
product.Name = "Apple";
|
||
product.ExpiryDate = new DateTime(2008, 12, 28, 0, 0, 0, DateTimeKind.Utc);
|
||
product.Price = 3.99M;
|
||
product.Sizes = new string[] { "Small" };
|
||
|
||
string output = JsonConvert.SerializeObject(product, new IsoDateTimeConverter());
|
||
|
||
XmlDocument xmlProduct = JsonConvert.DeserializeXmlNode(output, "product", true);
|
||
|
||
StringAssert.AreEqual(@"<product>
|
||
<Name>Apple</Name>
|
||
<ExpiryDate>2008-12-28T00:00:00Z</ExpiryDate>
|
||
<Price>3.99</Price>
|
||
<Sizes json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">Small</Sizes>
|
||
</product>", IndentXml(xmlProduct.InnerXml));
|
||
|
||
string output2 = JsonConvert.SerializeXmlNode(xmlProduct.DocumentElement, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""product"": {
|
||
""Name"": ""Apple"",
|
||
""ExpiryDate"": ""2008-12-28T00:00:00Z"",
|
||
""Price"": ""3.99"",
|
||
""Sizes"": [
|
||
""Small""
|
||
]
|
||
}
|
||
}", output2);
|
||
}
|
||
|
||
public class TestComplexArrayClass
|
||
{
|
||
public string Name { get; set; }
|
||
public IList<Product> Products { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void ComplexSingleItemArrayPropertySerialization()
|
||
{
|
||
TestComplexArrayClass o = new TestComplexArrayClass
|
||
{
|
||
Name = "Hi",
|
||
Products = new List<Product>
|
||
{
|
||
new Product { Name = "First" }
|
||
}
|
||
};
|
||
|
||
string output = JsonConvert.SerializeObject(o, new IsoDateTimeConverter());
|
||
|
||
XmlDocument xmlProduct = JsonConvert.DeserializeXmlNode(output, "test", true);
|
||
|
||
StringAssert.AreEqual(@"<test>
|
||
<Name>Hi</Name>
|
||
<Products json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<Name>First</Name>
|
||
<ExpiryDate>2000-01-01T00:00:00Z</ExpiryDate>
|
||
<Price>0</Price>
|
||
<Sizes />
|
||
</Products>
|
||
</test>", IndentXml(xmlProduct.InnerXml));
|
||
|
||
string output2 = JsonConvert.SerializeXmlNode(xmlProduct.DocumentElement, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""Name"": ""Hi"",
|
||
""Products"": [
|
||
{
|
||
""Name"": ""First"",
|
||
""ExpiryDate"": ""2000-01-01T00:00:00Z"",
|
||
""Price"": ""0"",
|
||
""Sizes"": null
|
||
}
|
||
]
|
||
}", output2);
|
||
}
|
||
|
||
[Test]
|
||
public void OmitRootObject()
|
||
{
|
||
string xml = @"<test>
|
||
<Name>Hi</Name>
|
||
<Name>Hi</Name>
|
||
<Products json:Array=""true"" xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<Name>First</Name>
|
||
<ExpiryDate>2000-01-01T00:00:00Z</ExpiryDate>
|
||
<Price>0</Price>
|
||
<Sizes />
|
||
</Products>
|
||
</test>";
|
||
|
||
XmlDocument d = new XmlDocument();
|
||
d.LoadXml(xml);
|
||
|
||
string output = JsonConvert.SerializeXmlNode(d, Formatting.Indented, true);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""Name"": [
|
||
""Hi"",
|
||
""Hi""
|
||
],
|
||
""Products"": [
|
||
{
|
||
""Name"": ""First"",
|
||
""ExpiryDate"": ""2000-01-01T00:00:00Z"",
|
||
""Price"": ""0"",
|
||
""Sizes"": null
|
||
}
|
||
]
|
||
}", output);
|
||
}
|
||
|
||
[Test]
|
||
public void EmtpyElementWithArrayAttributeShouldWriteAttributes()
|
||
{
|
||
string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
|
||
<root xmlns:json=""http://james.newtonking.com/projects/json"">
|
||
<A>
|
||
<B name=""sample"" json:Array=""true""/>
|
||
<C></C>
|
||
<C></C>
|
||
</A>
|
||
</root>";
|
||
|
||
XmlDocument d = new XmlDocument();
|
||
d.LoadXml(xml);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(d, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""?xml"": {
|
||
""@version"": ""1.0"",
|
||
""@encoding"": ""utf-8""
|
||
},
|
||
""root"": {
|
||
""A"": {
|
||
""B"": [
|
||
{
|
||
""@name"": ""sample""
|
||
}
|
||
],
|
||
""C"": [
|
||
"""",
|
||
""""
|
||
]
|
||
}
|
||
}
|
||
}", json);
|
||
|
||
XmlDocument d2 = JsonConvert.DeserializeXmlNode(json);
|
||
|
||
StringAssert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-8""?>
|
||
<root>
|
||
<A>
|
||
<B name=""sample"" />
|
||
<C></C>
|
||
<C></C>
|
||
</A>
|
||
</root>", ToStringWithDeclaration(d2, true));
|
||
}
|
||
|
||
[Test]
|
||
public void EmtpyElementWithArrayAttributeShouldWriteElement()
|
||
{
|
||
string xml = @"<root>
|
||
<Reports d1p1:Array=""true"" xmlns:d1p1=""http://james.newtonking.com/projects/json"" />
|
||
</root>";
|
||
|
||
XmlDocument d = new XmlDocument();
|
||
d.LoadXml(xml);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(d, Formatting.Indented);
|
||
|
||
StringAssert.AreEqual(@"{
|
||
""root"": {
|
||
""Reports"": [
|
||
{}
|
||
]
|
||
}
|
||
}", json);
|
||
}
|
||
|
||
[Test]
|
||
public void DeserializeNonInt64IntegerValues()
|
||
{
|
||
var dict = new Dictionary<string, object> { { "Int16", (short)1 }, { "Float", 2f }, { "Int32", 3 } };
|
||
var obj = JObject.FromObject(dict);
|
||
var serializer = JsonSerializer.Create(new JsonSerializerSettings { Converters = { new XmlNodeConverter() { DeserializeRootElementName = "root" } } });
|
||
using (var reader = obj.CreateReader())
|
||
{
|
||
var value = (XmlDocument)serializer.Deserialize(reader, typeof(XmlDocument));
|
||
|
||
Assert.AreEqual(@"<root><Int16>1</Int16><Float>2</Float><Int32>3</Int32></root>", value.InnerXml);
|
||
}
|
||
}
|
||
|
||
[Test]
|
||
public void DeserializingBooleanValues()
|
||
{
|
||
MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(@"{root:{""@booleanType"":true}}"));
|
||
MemoryStream xml = new MemoryStream();
|
||
|
||
JsonBodyToSoapXml(ms, xml);
|
||
|
||
string xmlString = System.Text.Encoding.UTF8.GetString(xml.ToArray());
|
||
|
||
Assert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-8""?><root booleanType=""true"" />", xmlString);
|
||
}
|
||
|
||
#if !(NETSTANDARD1_0 || NETSTANDARD1_3)
|
||
[Test]
|
||
public void IgnoreCultureForTypedAttributes()
|
||
{
|
||
var originalCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
|
||
|
||
try
|
||
{
|
||
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
|
||
|
||
// in russian culture value 12.27 will be written as 12,27
|
||
|
||
var serializer = JsonSerializer.Create(new JsonSerializerSettings
|
||
{
|
||
Converters = { new XmlNodeConverter() },
|
||
});
|
||
|
||
var json = new StringBuilder(@"{
|
||
""metrics"": {
|
||
""type"": ""CPULOAD"",
|
||
""@value"": 12.27
|
||
}
|
||
}");
|
||
|
||
using (var stringReader = new StringReader(json.ToString()))
|
||
using (var jsonReader = new JsonTextReader(stringReader))
|
||
{
|
||
var document = (XmlDocument)serializer.Deserialize(jsonReader, typeof(XmlDocument));
|
||
StringAssert.AreEqual(@"<metrics value=""12.27""><type>CPULOAD</type></metrics>", document.OuterXml);
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
System.Threading.Thread.CurrentThread.CurrentCulture = originalCulture;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void NullAttributeValue()
|
||
{
|
||
var node = JsonConvert.DeserializeXmlNode(@"{
|
||
""metrics"": {
|
||
""type"": ""CPULOAD"",
|
||
""@value"": null
|
||
}
|
||
}");
|
||
|
||
StringAssert.AreEqual(@"<metrics value=""""><type>CPULOAD</type></metrics>", node.OuterXml);
|
||
}
|
||
|
||
[Test]
|
||
public void NonStandardAttributeValues()
|
||
{
|
||
JObject o = new JObject
|
||
{
|
||
new JProperty("root", new JObject
|
||
{
|
||
new JProperty("@uri", new JValue(new Uri("http://localhost/"))),
|
||
new JProperty("@time_span", new JValue(TimeSpan.FromMinutes(1))),
|
||
new JProperty("@bytes", new JValue(System.Text.Encoding.UTF8.GetBytes("Hello world")))
|
||
})
|
||
};
|
||
|
||
using (var jsonReader = o.CreateReader())
|
||
{
|
||
var serializer = JsonSerializer.Create(new JsonSerializerSettings
|
||
{
|
||
Converters = { new XmlNodeConverter() },
|
||
});
|
||
|
||
var document = (XmlDocument)serializer.Deserialize(jsonReader, typeof(XmlDocument));
|
||
|
||
StringAssert.AreEqual(@"<root uri=""http://localhost/"" time_span=""00:01:00"" bytes=""SGVsbG8gd29ybGQ="" />", document.OuterXml);
|
||
}
|
||
}
|
||
|
||
[Test]
|
||
public void NonStandardElementsValues()
|
||
{
|
||
JObject o = new JObject
|
||
{
|
||
new JProperty("root", new JObject
|
||
{
|
||
new JProperty("uri", new JValue(new Uri("http://localhost/"))),
|
||
new JProperty("time_span", new JValue(TimeSpan.FromMinutes(1))),
|
||
new JProperty("bytes", new JValue(System.Text.Encoding.UTF8.GetBytes("Hello world")))
|
||
})
|
||
};
|
||
|
||
using (var jsonReader = o.CreateReader())
|
||
{
|
||
var serializer = JsonSerializer.Create(new JsonSerializerSettings
|
||
{
|
||
Converters = { new XmlNodeConverter() },
|
||
});
|
||
|
||
var document = (XmlDocument)serializer.Deserialize(jsonReader, typeof(XmlDocument));
|
||
|
||
StringAssert.AreEqual(@"<root><uri>http://localhost/</uri><time_span>00:01:00</time_span><bytes>SGVsbG8gd29ybGQ=</bytes></root>", document.OuterXml);
|
||
}
|
||
}
|
||
|
||
private static void JsonBodyToSoapXml(Stream json, Stream xml)
|
||
{
|
||
Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings();
|
||
settings.Converters.Add(new Newtonsoft.Json.Converters.XmlNodeConverter());
|
||
Newtonsoft.Json.JsonSerializer serializer = Newtonsoft.Json.JsonSerializer.Create(settings);
|
||
using (Newtonsoft.Json.JsonTextReader reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(json)))
|
||
{
|
||
XmlDocument doc = (XmlDocument)serializer.Deserialize(reader, typeof(XmlDocument));
|
||
if (reader.Read() && reader.TokenType != JsonToken.Comment)
|
||
{
|
||
throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
|
||
}
|
||
using (XmlWriter writer = XmlWriter.Create(xml))
|
||
{
|
||
doc.Save(writer);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void DeserializeXNodeDefaultNamespace()
|
||
{
|
||
string xaml = @"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:toolkit=""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"" Style=""{StaticResource trimFormGrid}"" x:Name=""TrimObjectForm"">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width=""63*"" />
|
||
<ColumnDefinition Width=""320*"" />
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions xmlns="""">
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
</Grid.RowDefinitions>
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordTypedTitle"" Grid.Column=""1"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordExternalReference"" Grid.Column=""1"" Grid.Row=""1"" xmlns="""" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateCreated"" Grid.Column=""1"" Grid.Row=""2"" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateDue"" Grid.Column=""1"" Grid.Row=""3"" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Author, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAuthor"" Grid.Column=""1"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Container, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordContainer"" Grid.Column=""1"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordIsEnclosed"" Grid.Column=""1"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAssignee"" Grid.Column=""1"" Grid.Row=""7"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Title (Free Text Part)"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""External ID"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Created"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""2"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Due"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""3"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Author"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Container"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Enclosed?"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Assignee"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""7"" xmlns="""" />
|
||
</Grid>";
|
||
|
||
string json = JsonConvert.SerializeXNode(XDocument.Parse(xaml), Formatting.Indented);
|
||
|
||
string expectedJson = @"{
|
||
""Grid"": {
|
||
""@xmlns"": ""http://schemas.microsoft.com/winfx/2006/xaml/presentation"",
|
||
""@xmlns:x"": ""http://schemas.microsoft.com/winfx/2006/xaml"",
|
||
""@xmlns:toolkit"": ""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"",
|
||
""@Style"": ""{StaticResource trimFormGrid}"",
|
||
""@x:Name"": ""TrimObjectForm"",
|
||
""Grid.ColumnDefinitions"": {
|
||
""ColumnDefinition"": [
|
||
{
|
||
""@Width"": ""63*""
|
||
},
|
||
{
|
||
""@Width"": ""320*""
|
||
}
|
||
]
|
||
},
|
||
""Grid.RowDefinitions"": {
|
||
""@xmlns"": """",
|
||
""RowDefinition"": [
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null
|
||
]
|
||
},
|
||
""TextBox"": [
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordTypedTitle"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""0"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordExternalReference"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""1"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Author, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordAuthor"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""4"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Container, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordContainer"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""5"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordIsEnclosed"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""6"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordAssignee"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""7"",
|
||
""@xmlns"": """"
|
||
}
|
||
],
|
||
""toolkit:DatePicker"": [
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_DP}"",
|
||
""@Value"": ""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordDateCreated"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""2""
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_DP}"",
|
||
""@Value"": ""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordDateDue"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""3""
|
||
}
|
||
],
|
||
""TextBlock"": [
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Title (Free Text Part)"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""0"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""External ID"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""1"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Date Created"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""2"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Date Due"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""3"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Author"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""4"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Container"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""5"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Enclosed?"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""6"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Assignee"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""7"",
|
||
""@xmlns"": """"
|
||
}
|
||
]
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expectedJson, json);
|
||
|
||
XNode node = JsonConvert.DeserializeXNode(json);
|
||
|
||
string xaml2 = node.ToString();
|
||
|
||
string expectedXaml = @"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:toolkit=""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"" Style=""{StaticResource trimFormGrid}"" x:Name=""TrimObjectForm"">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width=""63*"" />
|
||
<ColumnDefinition Width=""320*"" />
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions xmlns="""">
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
</Grid.RowDefinitions>
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordTypedTitle"" Grid.Column=""1"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordExternalReference"" Grid.Column=""1"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Author, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAuthor"" Grid.Column=""1"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Container, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordContainer"" Grid.Column=""1"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordIsEnclosed"" Grid.Column=""1"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAssignee"" Grid.Column=""1"" Grid.Row=""7"" xmlns="""" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateCreated"" Grid.Column=""1"" Grid.Row=""2"" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateDue"" Grid.Column=""1"" Grid.Row=""3"" />
|
||
<TextBlock Grid.Column=""0"" Text=""Title (Free Text Part)"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""External ID"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Created"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""2"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Due"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""3"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Author"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Container"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Enclosed?"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Assignee"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""7"" xmlns="""" />
|
||
</Grid>";
|
||
|
||
StringAssert.AreEqual(expectedXaml, xaml2);
|
||
}
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void DeserializeXmlNodeDefaultNamespace()
|
||
{
|
||
string xaml = @"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:toolkit=""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"" Style=""{StaticResource trimFormGrid}"" x:Name=""TrimObjectForm"">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width=""63*"" />
|
||
<ColumnDefinition Width=""320*"" />
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions xmlns="""">
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
</Grid.RowDefinitions>
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordTypedTitle"" Grid.Column=""1"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordExternalReference"" Grid.Column=""1"" Grid.Row=""1"" xmlns="""" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateCreated"" Grid.Column=""1"" Grid.Row=""2"" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateDue"" Grid.Column=""1"" Grid.Row=""3"" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Author, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAuthor"" Grid.Column=""1"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Container, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordContainer"" Grid.Column=""1"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordIsEnclosed"" Grid.Column=""1"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAssignee"" Grid.Column=""1"" Grid.Row=""7"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Title (Free Text Part)"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""External ID"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Created"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""2"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Due"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""3"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Author"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Container"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Enclosed?"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Assignee"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""7"" xmlns="""" />
|
||
</Grid>";
|
||
|
||
XmlDocument document = new XmlDocument();
|
||
document.LoadXml(xaml);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(document, Formatting.Indented);
|
||
|
||
string expectedJson = @"{
|
||
""Grid"": {
|
||
""@xmlns"": ""http://schemas.microsoft.com/winfx/2006/xaml/presentation"",
|
||
""@xmlns:x"": ""http://schemas.microsoft.com/winfx/2006/xaml"",
|
||
""@xmlns:toolkit"": ""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"",
|
||
""@Style"": ""{StaticResource trimFormGrid}"",
|
||
""@x:Name"": ""TrimObjectForm"",
|
||
""Grid.ColumnDefinitions"": {
|
||
""ColumnDefinition"": [
|
||
{
|
||
""@Width"": ""63*""
|
||
},
|
||
{
|
||
""@Width"": ""320*""
|
||
}
|
||
]
|
||
},
|
||
""Grid.RowDefinitions"": {
|
||
""@xmlns"": """",
|
||
""RowDefinition"": [
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
null
|
||
]
|
||
},
|
||
""TextBox"": [
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordTypedTitle"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""0"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordExternalReference"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""1"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Author, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordAuthor"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""4"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Container, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordContainer"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""5"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordIsEnclosed"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""6"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_TB}"",
|
||
""@Text"": ""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordAssignee"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""7"",
|
||
""@xmlns"": """"
|
||
}
|
||
],
|
||
""toolkit:DatePicker"": [
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_DP}"",
|
||
""@Value"": ""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordDateCreated"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""2""
|
||
},
|
||
{
|
||
""@Style"": ""{StaticResource trimFormGrid_DP}"",
|
||
""@Value"": ""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"",
|
||
""@Name"": ""RecordDateDue"",
|
||
""@Grid.Column"": ""1"",
|
||
""@Grid.Row"": ""3""
|
||
}
|
||
],
|
||
""TextBlock"": [
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Title (Free Text Part)"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""0"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""External ID"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""1"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Date Created"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""2"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Date Due"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""3"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Author"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""4"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Container"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""5"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Enclosed?"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""6"",
|
||
""@xmlns"": """"
|
||
},
|
||
{
|
||
""@Grid.Column"": ""0"",
|
||
""@Text"": ""Assignee"",
|
||
""@Style"": ""{StaticResource trimFormGrid_LBL}"",
|
||
""@Grid.Row"": ""7"",
|
||
""@xmlns"": """"
|
||
}
|
||
]
|
||
}
|
||
}";
|
||
|
||
StringAssert.AreEqual(expectedJson, json);
|
||
|
||
XmlNode node = JsonConvert.DeserializeXmlNode(json);
|
||
|
||
StringWriter sw = new StringWriter();
|
||
XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings
|
||
{
|
||
Indent = true,
|
||
OmitXmlDeclaration = true
|
||
});
|
||
node.WriteTo(writer);
|
||
writer.Flush();
|
||
|
||
string xaml2 = sw.ToString();
|
||
|
||
string expectedXaml = @"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:toolkit=""clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"" Style=""{StaticResource trimFormGrid}"" x:Name=""TrimObjectForm"">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width=""63*"" />
|
||
<ColumnDefinition Width=""320*"" />
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions xmlns="""">
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
<RowDefinition />
|
||
</Grid.RowDefinitions>
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding TypedTitle, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordTypedTitle"" Grid.Column=""1"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding ExternalReference, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordExternalReference"" Grid.Column=""1"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Author, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAuthor"" Grid.Column=""1"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Container, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordContainer"" Grid.Column=""1"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding IsEnclosed, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordIsEnclosed"" Grid.Column=""1"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBox Style=""{StaticResource trimFormGrid_TB}"" Text=""{Binding Assignee, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordAssignee"" Grid.Column=""1"" Grid.Row=""7"" xmlns="""" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateCreated, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateCreated"" Grid.Column=""1"" Grid.Row=""2"" />
|
||
<toolkit:DatePicker Style=""{StaticResource trimFormGrid_DP}"" Value=""{Binding DateDue, Converter={StaticResource trimPropertyConverter}}"" Name=""RecordDateDue"" Grid.Column=""1"" Grid.Row=""3"" />
|
||
<TextBlock Grid.Column=""0"" Text=""Title (Free Text Part)"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""0"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""External ID"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""1"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Created"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""2"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Date Due"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""3"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Author"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""4"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Container"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""5"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Enclosed?"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""6"" xmlns="""" />
|
||
<TextBlock Grid.Column=""0"" Text=""Assignee"" Style=""{StaticResource trimFormGrid_LBL}"" Grid.Row=""7"" xmlns="""" />
|
||
</Grid>";
|
||
|
||
StringAssert.AreEqual(expectedXaml, xaml2);
|
||
}
|
||
|
||
[Test]
|
||
public void DeserializeAttributePropertyNotAtStart()
|
||
{
|
||
string json = @"{""item"": {""@action"": ""update"", ""@itemid"": ""1"", ""elements"": [{""@action"": ""none"", ""@id"": ""2""},{""@action"": ""none"", ""@id"": ""3""}],""@description"": ""temp""}}";
|
||
|
||
XmlDocument xmldoc = JsonConvert.DeserializeXmlNode(json);
|
||
|
||
Assert.AreEqual(@"<item action=""update"" itemid=""1"" description=""temp""><elements action=""none"" id=""2"" /><elements action=""none"" id=""3"" /></item>", xmldoc.InnerXml);
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void SerializingXmlNamespaceScope()
|
||
{
|
||
var xmlString = @"<root xmlns=""http://www.example.com/ns"">
|
||
<a/>
|
||
<bns:b xmlns:bns=""http://www.example.com/ns""/>
|
||
<c/>
|
||
</root>";
|
||
|
||
#if !NET20
|
||
var xml = XElement.Parse(xmlString);
|
||
|
||
var json1 = JsonConvert.SerializeObject(xml);
|
||
|
||
Assert.AreEqual(@"{""root"":{""@xmlns"":""http://www.example.com/ns"",""a"":null,""bns:b"":{""@xmlns:bns"":""http://www.example.com/ns""},""c"":null}}", json1);
|
||
#endif
|
||
#if !(PORTABLE)
|
||
var xml1 = new XmlDocument();
|
||
xml1.LoadXml(xmlString);
|
||
|
||
var json2 = JsonConvert.SerializeObject(xml1);
|
||
|
||
Assert.AreEqual(@"{""root"":{""@xmlns"":""http://www.example.com/ns"",""a"":null,""bns:b"":{""@xmlns:bns"":""http://www.example.com/ns""},""c"":null}}", json2);
|
||
#endif
|
||
}
|
||
|
||
#if !NET20
|
||
public class NullableXml
|
||
{
|
||
public string Name;
|
||
public XElement notNull;
|
||
public XElement isNull;
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeAndDeserializeNullableXml()
|
||
{
|
||
var xml = new NullableXml { Name = "test", notNull = XElement.Parse("<root>test</root>") };
|
||
var json = JsonConvert.SerializeObject(xml);
|
||
|
||
var w2 = JsonConvert.DeserializeObject<NullableXml>(json);
|
||
Assert.AreEqual(xml.Name, w2.Name);
|
||
Assert.AreEqual(xml.isNull, w2.isNull);
|
||
Assert.AreEqual(xml.notNull.ToString(), w2.notNull.ToString());
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void SerializeAndDeserializeXElementWithNamespaceInChildrenRootDontHaveNameSpace()
|
||
{
|
||
var xmlString = @"<root>
|
||
<b xmlns='http://www.example.com/ns'>Asd</b>
|
||
<c>AAA</c>
|
||
<test>adad</test>
|
||
</root>";
|
||
|
||
var xml = XElement.Parse(xmlString);
|
||
|
||
var json1 = JsonConvert.SerializeXNode(xml);
|
||
var xmlBack = JsonConvert.DeserializeObject<XElement>(json1);
|
||
|
||
var equals = XElement.DeepEquals(xmlBack, xml);
|
||
Assert.IsTrue(equals);
|
||
}
|
||
#endif
|
||
|
||
#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void SerializeAndDeserializeXmlElementWithNamespaceInChildrenRootDontHaveNameSpace()
|
||
{
|
||
var xmlString = @"<root>
|
||
<b xmlns='http://www.example.com/ns'>Asd</b>
|
||
<c>AAA</c>
|
||
<test>adad</test>
|
||
</root>";
|
||
|
||
XmlDocument xml = new XmlDocument();
|
||
xml.LoadXml(xmlString);
|
||
|
||
var json1 = JsonConvert.SerializeXmlNode(xml);
|
||
var xmlBack = JsonConvert.DeserializeObject<XmlDocument>(json1);
|
||
|
||
Assert.AreEqual(@"<root><b xmlns=""http://www.example.com/ns"">Asd</b><c>AAA</c><test>adad</test></root>", xmlBack.OuterXml);
|
||
}
|
||
|
||
#if !(NET20 || NET35 || PORTABLE || PORTABLE40) || NETSTANDARD1_3 || NETSTANDARD2_0 || NET6_0_OR_GREATER
|
||
[Test]
|
||
public void DeserializeBigInteger()
|
||
{
|
||
var json = "{\"DocumentId\":13779965364495889899 }";
|
||
|
||
XmlDocument node = JsonConvert.DeserializeXmlNode(json);
|
||
|
||
Assert.AreEqual("<DocumentId>13779965364495889899</DocumentId>", node.OuterXml);
|
||
|
||
string json2 = JsonConvert.SerializeXmlNode(node);
|
||
|
||
Assert.AreEqual(@"{""DocumentId"":""13779965364495889899""}", json2);
|
||
}
|
||
#endif
|
||
|
||
[Test]
|
||
public void DeserializeXmlIncompatibleCharsInPropertyName()
|
||
{
|
||
var json = "{\"%name\":\"value\"}";
|
||
|
||
XmlDocument node = JsonConvert.DeserializeXmlNode(json);
|
||
|
||
Assert.AreEqual("<_x0025_name>value</_x0025_name>", node.OuterXml);
|
||
|
||
string json2 = JsonConvert.SerializeXmlNode(node);
|
||
|
||
Assert.AreEqual(json, json2);
|
||
}
|
||
|
||
[Test]
|
||
public void RootPropertyError()
|
||
{
|
||
string json = @"{
|
||
""$id"": ""1"",
|
||
""AOSLocaleName"": ""en-US"",
|
||
""AXLanguage"": ""EN-AU"",
|
||
""Company"": ""AURE"",
|
||
""CompanyTimeZone"": 8,
|
||
""CurrencyInfo"": {
|
||
""$id"": ""2"",
|
||
""CurrencyCode"": ""AUD"",
|
||
""Description"": ""Australian Dollar"",
|
||
""ExchangeRate"": 100.0,
|
||
""ISOCurrencyCode"": ""AUD"",
|
||
""Prefix"": """",
|
||
""Suffix"": """"
|
||
},
|
||
""IsSysAdmin"": true,
|
||
""UserId"": ""lamar.miller"",
|
||
""UserPreferredCalendar"": 0,
|
||
""UserPreferredTimeZone"": 8
|
||
}";
|
||
|
||
ExceptionAssert.Throws<JsonSerializationException>(
|
||
() => JsonConvert.DeserializeXmlNode(json),
|
||
"JSON root object has property '$id' that will be converted to an attribute. A root object cannot have any attribute properties. Consider specifying a DeserializeRootElementName. Path '$id', line 2, position 12.");
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeEmptyNodeAndOmitRoot()
|
||
{
|
||
string xmlString = @"<myemptynode />";
|
||
|
||
XmlDocument xml = new XmlDocument();
|
||
xml.LoadXml(xmlString);
|
||
|
||
string json = JsonConvert.SerializeXmlNode(xml, Formatting.Indented, true);
|
||
|
||
Assert.AreEqual("null", json);
|
||
}
|
||
#endif
|
||
|
||
#if !NET20
|
||
[Test]
|
||
public void Serialize_XDocument_NoRoot()
|
||
{
|
||
XDocument d = new XDocument();
|
||
|
||
string json = JsonConvert.SerializeXNode(d);
|
||
|
||
Assert.AreEqual(@"{}", json);
|
||
}
|
||
|
||
[Test]
|
||
public void Deserialize_XDocument_NoRoot()
|
||
{
|
||
XDocument d = JsonConvert.DeserializeXNode(@"{}");
|
||
|
||
Assert.AreEqual(null, d.Root);
|
||
Assert.AreEqual(null, d.Declaration);
|
||
}
|
||
|
||
[Test]
|
||
public void Serialize_XDocument_NoRootWithDeclaration()
|
||
{
|
||
XDocument d = new XDocument();
|
||
d.Declaration = new XDeclaration("Version!", "Encoding!", "Standalone!");
|
||
|
||
string json = JsonConvert.SerializeXNode(d);
|
||
|
||
Assert.AreEqual(@"{""?xml"":{""@version"":""Version!"",""@encoding"":""Encoding!"",""@standalone"":""Standalone!""}}", json);
|
||
}
|
||
|
||
[Test]
|
||
public void Deserialize_XDocument_NoRootWithDeclaration()
|
||
{
|
||
XDocument d = JsonConvert.DeserializeXNode(@"{""?xml"":{""@version"":""Version!"",""@encoding"":""Encoding!"",""@standalone"":""Standalone!""}}");
|
||
|
||
Assert.AreEqual(null, d.Root);
|
||
Assert.AreEqual("Version!", d.Declaration.Version);
|
||
Assert.AreEqual("Encoding!", d.Declaration.Encoding);
|
||
Assert.AreEqual("Standalone!", d.Declaration.Standalone);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Unspecified()
|
||
{
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual("2014-01-23T00:00:00", dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Unspecified: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Utc()
|
||
{
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00Z""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual("2014-01-23T00:00:00Z", dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Utc: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Local()
|
||
{
|
||
DateTime dt = DateTime.Parse("2014-01-23T00:00:00+01:00");
|
||
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00+01:00""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual(dt.ToString("yyyy-MM-ddTHH:mm:sszzzzzzz", CultureInfo.InvariantCulture), dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Local: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Unspecified_Precision()
|
||
{
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00.1234567""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual("2014-01-23T00:00:00.1234567", dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Unspecified: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Utc_Precision()
|
||
{
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00.1234567Z""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual("2014-01-23T00:00:00.1234567Z", dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Utc: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void DateTimeToXml_Local_Precision()
|
||
{
|
||
DateTime dt = DateTime.Parse("2014-01-23T00:00:00.1234567+01:00");
|
||
|
||
string json = @"{""CreatedDate"": ""2014-01-23T00:00:00.1234567+01:00""}";
|
||
var dxml = JsonConvert.DeserializeXNode(json, "root");
|
||
Assert.AreEqual(dt.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture), dxml.Root.Element("CreatedDate").Value);
|
||
|
||
Console.WriteLine("DateTimeToXml_Local: " + dxml.Root.Element("CreatedDate").Value);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeEmptyNodeAndOmitRoot_XElement()
|
||
{
|
||
string xmlString = @"<myemptynode />";
|
||
|
||
var xml = XElement.Parse(xmlString);
|
||
|
||
string json = JsonConvert.SerializeXNode(xml, Formatting.Indented, true);
|
||
|
||
Assert.AreEqual("null", json);
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeElementExplicitAttributeNamespace()
|
||
{
|
||
var original = XElement.Parse("<MyElement xmlns=\"http://example.com\" />");
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", original.ToString());
|
||
|
||
var json = JsonConvert.SerializeObject(original);
|
||
Assert.AreEqual(@"{""MyElement"":{""@xmlns"":""http://example.com""}}", json);
|
||
|
||
var deserialized = JsonConvert.DeserializeObject<XElement>(json);
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", deserialized.ToString());
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeElementImplicitAttributeNamespace()
|
||
{
|
||
var original = new XElement("{http://example.com}MyElement");
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", original.ToString());
|
||
|
||
var json = JsonConvert.SerializeObject(original);
|
||
Assert.AreEqual(@"{""MyElement"":{""@xmlns"":""http://example.com""}}", json);
|
||
|
||
var deserialized = JsonConvert.DeserializeObject<XElement>(json);
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", deserialized.ToString());
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDocumentExplicitAttributeNamespace()
|
||
{
|
||
var original = XDocument.Parse("<MyElement xmlns=\"http://example.com\" />");
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", original.ToString());
|
||
|
||
var json = JsonConvert.SerializeObject(original);
|
||
Assert.AreEqual(@"{""MyElement"":{""@xmlns"":""http://example.com""}}", json);
|
||
|
||
var deserialized = JsonConvert.DeserializeObject<XDocument>(json);
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", deserialized.ToString());
|
||
}
|
||
|
||
[Test]
|
||
public void SerializeDocumentImplicitAttributeNamespace()
|
||
{
|
||
var original = new XDocument(new XElement("{http://example.com}MyElement"));
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", original.ToString());
|
||
|
||
var json = JsonConvert.SerializeObject(original);
|
||
Assert.AreEqual(@"{""MyElement"":{""@xmlns"":""http://example.com""}}", json);
|
||
|
||
var deserialized = JsonConvert.DeserializeObject<XDocument>(json);
|
||
Assert.AreEqual(@"<MyElement xmlns=""http://example.com"" />", deserialized.ToString());
|
||
}
|
||
|
||
public class Model
|
||
{
|
||
public XElement Document { get; set; }
|
||
}
|
||
|
||
[Test]
|
||
public void DeserializeDateInElementText()
|
||
{
|
||
Model model = new Model();
|
||
model.Document = new XElement("Value", new XAttribute("foo", "bar"))
|
||
{
|
||
Value = "2001-01-01T11:11:11"
|
||
};
|
||
|
||
var serializer = JsonSerializer.Create(new JsonSerializerSettings
|
||
{
|
||
Converters = new List<JsonConverter>(new[] { new XmlNodeConverter() })
|
||
});
|
||
|
||
var json = new StringBuilder(1024);
|
||
|
||
using (var stringWriter = new StringWriter(json, CultureInfo.InvariantCulture))
|
||
using (var jsonWriter = new JsonTextWriter(stringWriter))
|
||
{
|
||
jsonWriter.Formatting = Formatting.None;
|
||
serializer.Serialize(jsonWriter, model);
|
||
|
||
Assert.AreEqual(@"{""Document"":{""Value"":{""@foo"":""bar"",""#text"":""2001-01-01T11:11:11""}}}", json.ToString());
|
||
}
|
||
|
||
using (var stringReader = new StringReader(json.ToString()))
|
||
using (var jsonReader = new JsonTextReader(stringReader))
|
||
{
|
||
var document = (XDocument)serializer.Deserialize(jsonReader, typeof(XDocument));
|
||
|
||
StringAssert.AreEqual(@"<Document>
|
||
<Value foo=""bar"">2001-01-01T11:11:11</Value>
|
||
</Document>", document.ToString());
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
#endif |