diff options
author | JamesNK <james@newtonking.com> | 2010-12-27 07:00:43 +0300 |
---|---|---|
committer | JamesNK <james@newtonking.com> | 2010-12-27 07:00:43 +0300 |
commit | 87a2bbf831b1307f8763059872fa74203c60e09e (patch) | |
tree | f7d28e1cb07ba83085691b747a8ec20cac6cca7d /Src | |
parent | 2c92f69c741fd5443f1b24cbd4efd45b67ea4948 (diff) |
-Added WriteArrayAttribute to XmlNodeConverter to include an attribute to help round tripping JSON and XML
-Added OmitRootObject to XmlNodeConverter to skip writing the root JSON object when converting XML
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs | 239 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs | 164 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/JsonConvert.cs | 60 |
3 files changed, 413 insertions, 50 deletions
diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index 6c49c1e..3dfe29d 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -25,7 +25,9 @@ #if !SILVERLIGHT
using System;
+using System.Collections.Generic;
using Newtonsoft.Json.Tests.Serialization;
+using Newtonsoft.Json.Tests.TestObjects;
using NUnit.Framework;
using Newtonsoft.Json;
using System.IO;
@@ -423,12 +425,12 @@ namespace Newtonsoft.Json.Tests.Converters string xml = @"<?xml version=""1.0"" standalone=""no""?>
<root>
<person id=""1"">
- <name>Alan</name>
- <url>http://www.google.com</url>
+ <name>Alan</name>
+ <url>http://www.google.com</url>
</person>
<person id=""2"">
- <name>Louis</name>
- <url>http://www.yahoo.com</url>
+ <name>Louis</name>
+ <url>http://www.yahoo.com</url>
</person>
</root>";
@@ -651,19 +653,110 @@ namespace Newtonsoft.Json.Tests.Converters [
""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""
]
]
}";
XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot");
- Assert.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></myRoot>", newDoc.InnerXml);
+ string xml = IndentXml(newDoc.InnerXml);
+
+ Assert.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));
#if !NET20
XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot");
- Assert.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></myRoot>", newXDoc.ToString(SaveOptions.DisableFormatting));
+ Assert.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
+
+ string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented);
+ Console.WriteLine(newJson);
+ }
+
+ [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""
+ ]
+ ]
+}";
+
+ XmlDocument newDoc = JsonConvert.DeserializeXmlNode(json, "myRoot", true);
+
+ Assert.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));
+
+#if !NET20
+ XDocument newXDoc = JsonConvert.DeserializeXNode(json, "myRoot", true);
+
+ Console.WriteLine(IndentXml(newXDoc.ToString(SaveOptions.DisableFormatting)));
+
+ Assert.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
+
+ string newJson = JsonConvert.SerializeXmlNode(newDoc, Formatting.Indented, true);
+ Assert.AreEqual(json, newJson);
}
[Test]
@@ -992,6 +1085,140 @@ namespace Newtonsoft.Json.Tests.Converters DeserializeXmlNode(json);
}
+
+ [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);
+
+ Assert.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);
+
+ Assert.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);
+
+ Assert.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);
+
+ Assert.AreEqual(@"{
+ ""Name"": ""Hi"",
+ ""Products"": [
+ {
+ ""Name"": ""First"",
+ ""ExpiryDate"": ""2000-01-01T00:00:00Z"",
+ ""Price"": ""0"",
+ ""Sizes"": null
+ }
+ ]
+}", output2);
+ }
+
+ 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();
+ }
+
+ [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);
+
+ Assert.AreEqual(@"{
+ ""Name"": [
+ ""Hi"",
+ ""Hi""
+ ],
+ ""Products"": [
+ {
+ ""Name"": ""First"",
+ ""ExpiryDate"": ""2000-01-01T00:00:00Z"",
+ ""Price"": ""0"",
+ ""Sizes"": null
+ }
+ ]
+}", output);
+ }
}
}
#endif
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs index d9b9292..8c388df 100644 --- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -136,6 +136,11 @@ namespace Newtonsoft.Json.Converters _element.SetAttributeNode((XmlAttribute) xmlAttributeWrapper.WrappedNode);
}
+
+ public string GetPrefixOfNamespace(string namespaceURI)
+ {
+ return _element.GetPrefixOfNamespace(namespaceURI);
+ }
}
internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration
@@ -294,6 +299,7 @@ namespace Newtonsoft.Json.Converters internal interface IXmlElement : IXmlNode
{
void SetAttributeNode(IXmlNode attribute);
+ string GetPrefixOfNamespace(string namespaceURI);
}
internal interface IXmlNode
@@ -726,6 +732,11 @@ namespace Newtonsoft.Json.Converters {
get { return Element.Name.NamespaceName; }
}
+
+ public string GetPrefixOfNamespace(string namespaceURI)
+ {
+ return Element.GetPrefixOfNamespace(namespaceURI);
+ }
}
#endif
#endregion
@@ -749,6 +760,19 @@ namespace Newtonsoft.Json.Converters /// <value>The name of the deserialize root element.</value>
public string DeserializeRootElementName { get; set; }
+ /// <summary>
+ /// Gets or sets a flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ /// </summary>
+ /// <value><c>true</c> if the array attibute is written to the XML; otherwise, <c>false</c>.</value>
+ public bool WriteArrayAttribute { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to write the root JSON object.
+ /// </summary>
+ /// <value><c>true</c> if the JSON root object is omitted; otherwise, <c>false</c>.</value>
+ public bool OmitRootObject { get; set; }
+
#region Writing
/// <summary>
/// Writes the JSON representation of the object.
@@ -763,9 +787,13 @@ namespace Newtonsoft.Json.Converters XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
PushParentNamespaces(node, manager);
- writer.WriteStartObject();
- SerializeNode(writer, node, manager, true);
- writer.WriteEndObject();
+ if (!OmitRootObject)
+ writer.WriteStartObject();
+
+ SerializeNode(writer, node, manager, !OmitRootObject);
+
+ if (!OmitRootObject)
+ writer.WriteEndObject();
}
private IXmlNode WrapXml(object value)
@@ -856,7 +884,16 @@ namespace Newtonsoft.Json.Converters }
}
- private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager)
+ private bool IsArray(IXmlNode node)
+ {
+ IXmlNode jsonArrayAttribute = (node.Attributes != null)
+ ? node.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceURI == JsonNamespaceUri)
+ : null;
+
+ return (jsonArrayAttribute != null && XmlConvert.ToBoolean(jsonArrayAttribute.Value));
+ }
+
+ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
{
// group nodes together by name
Dictionary<string, List<IXmlNode>> nodesGroupedByName = new Dictionary<string, List<IXmlNode>>();
@@ -885,14 +922,7 @@ namespace Newtonsoft.Json.Converters if (groupedNodes.Count == 1)
{
- IXmlNode singleNode = groupedNodes[0];
- IXmlNode jsonArrayAttribute = (singleNode.Attributes != null)
- ? singleNode.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceURI == JsonNamespaceUri)
- : null;
- if (jsonArrayAttribute != null)
- writeArray = XmlConvert.ToBoolean(jsonArrayAttribute.Value);
- else
- writeArray = false;
+ writeArray = IsArray(groupedNodes[0]);
}
else
{
@@ -901,12 +931,15 @@ namespace Newtonsoft.Json.Converters if (!writeArray)
{
- SerializeNode(writer, groupedNodes[0], manager, true);
+ SerializeNode(writer, groupedNodes[0], manager, writePropertyName);
}
else
{
string elementNames = nodeNameGroup.Key;
- writer.WritePropertyName(elementNames);
+
+ if (writePropertyName)
+ writer.WritePropertyName(elementNames);
+
writer.WriteStartArray();
for (int i = 0; i < groupedNodes.Count; i++)
@@ -925,47 +958,54 @@ namespace Newtonsoft.Json.Converters {
case XmlNodeType.Document:
case XmlNodeType.DocumentFragment:
- SerializeGroupedNodes(writer, node, manager);
+ SerializeGroupedNodes(writer, node, manager, writePropertyName);
break;
case XmlNodeType.Element:
- foreach (IXmlNode attribute in node.Attributes)
+ if (IsArray(node) && node.ChildNodes.All(n => n.LocalName == node.LocalName))
+ {
+ SerializeGroupedNodes(writer, node, manager, false);
+ }
+ else
{
- if (attribute.NamespaceURI == "http://www.w3.org/2000/xmlns/")
+ foreach (IXmlNode attribute in node.Attributes)
{
- string prefix = (attribute.LocalName != "xmlns")
- ? attribute.LocalName
- : string.Empty;
+ if (attribute.NamespaceURI == "http://www.w3.org/2000/xmlns/")
+ {
+ string prefix = (attribute.LocalName != "xmlns")
+ ? attribute.LocalName
+ : string.Empty;
- manager.AddNamespace(prefix, attribute.Value);
+ manager.AddNamespace(prefix, attribute.Value);
+ }
}
- }
- if (writePropertyName)
- writer.WritePropertyName(GetPropertyName(node, manager));
-
- if (ValueAttributes(node.Attributes).Count() == 0 && node.ChildNodes.Count == 1
- && node.ChildNodes[0].NodeType == XmlNodeType.Text)
- {
- // write elements with a single text child as a name value pair
- writer.WriteValue(node.ChildNodes[0].Value);
- }
- else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
- {
- // empty element
- writer.WriteNull();
- }
- else
- {
- writer.WriteStartObject();
+ if (writePropertyName)
+ writer.WritePropertyName(GetPropertyName(node, manager));
- for (int i = 0; i < node.Attributes.Count; i++)
+ if (ValueAttributes(node.Attributes).Count() == 0 && node.ChildNodes.Count == 1
+ && node.ChildNodes[0].NodeType == XmlNodeType.Text)
+ {
+ // write elements with a single text child as a name value pair
+ writer.WriteValue(node.ChildNodes[0].Value);
+ }
+ else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
{
- SerializeNode(writer, node.Attributes[i], manager, true);
+ // empty element
+ writer.WriteNull();
}
+ else
+ {
+ writer.WriteStartObject();
+
+ for (int i = 0; i < node.Attributes.Count; i++)
+ {
+ SerializeNode(writer, node.Attributes[i], manager, true);
+ }
- SerializeGroupedNodes(writer, node, manager);
+ SerializeGroupedNodes(writer, node, manager, true);
- writer.WriteEndObject();
+ writer.WriteEndObject();
+ }
}
break;
@@ -1116,6 +1156,7 @@ namespace Newtonsoft.Json.Converters {
if (reader.TokenType == JsonToken.StartArray)
{
+ // handle nested arrays
ReadArrayElements(reader, document, propertyName, currentNode, manager);
return;
}
@@ -1200,10 +1241,39 @@ namespace Newtonsoft.Json.Converters currentNode.AppendChild(nestedArrayElement);
+ int count = 0;
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
+ count++;
+ }
+
+ if (WriteArrayAttribute)
+ {
+ AddJsonArrayAttribute(nestedArrayElement, document);
}
+
+ if (count == 1 && WriteArrayAttribute)
+ {
+ IXmlElement arrayElement = nestedArrayElement.ChildNodes.CastValid<IXmlElement>().Single(n => n.LocalName == propertyName);
+ AddJsonArrayAttribute(arrayElement, document);
+ }
+ }
+
+ private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document)
+ {
+ element.SetAttributeNode(document.CreateAttribute("json:Array", JsonNamespaceUri, "true"));
+
+#if !NET20
+ // linq to xml doesn't automatically include prefixes via the namespace manager
+ if (element is XElementWrapper)
+ {
+ if (element.GetPrefixOfNamespace(JsonNamespaceUri) == null)
+ {
+ element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", JsonNamespaceUri));
+ }
+ }
+#endif
}
private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
@@ -1355,9 +1425,17 @@ namespace Newtonsoft.Json.Converters if (reader.TokenType == JsonToken.StartArray)
{
+ int count = 0;
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
DeserializeValue(reader, document, manager, propertyName, currentNode);
+ count++;
+ }
+
+ if (count == 1 && WriteArrayAttribute)
+ {
+ IXmlElement arrayElement = currentNode.ChildNodes.CastValid<IXmlElement>().Single(n => n.LocalName == propertyName);
+ AddJsonArrayAttribute(arrayElement, document);
}
}
else
diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index 38b56cd..f3a0978 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -786,6 +786,20 @@ namespace Newtonsoft.Json }
/// <summary>
+ /// Serializes the XML node to a JSON string.
+ /// </summary>
+ /// <param name="node">The node to serialize.</param>
+ /// <param name="formatting">Indicates how the output is formatted.</param>
+ /// <param name="omitRootObject">Omits writing the root object.</param>
+ /// <returns>A JSON string of the XmlNode.</returns>
+ public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
+
+ return SerializeObject(node, formatting, converter);
+ }
+
+ /// <summary>
/// Deserializes the XmlNode from a JSON string.
/// </summary>
/// <param name="value">The JSON string.</param>
@@ -803,8 +817,24 @@ namespace Newtonsoft.Json /// <returns>The deserialized XmlNode</returns>
public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
{
+ return DeserializeXmlNode(value, deserializeRootElementName, false);
+ }
+
+ /// <summary>
+ /// Deserializes the XmlNode from a JSON string nested in a root elment.
+ /// </summary>
+ /// <param name="value">The JSON string.</param>
+ /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+ /// <param name="writeArrayAttribute">
+ /// A flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ /// </param>
+ /// <returns>The deserialized XmlNode</returns>
+ public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+ {
XmlNodeConverter converter = new XmlNodeConverter();
converter.DeserializeRootElementName = deserializeRootElementName;
+ converter.WriteArrayAttribute = writeArrayAttribute;
return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
}
@@ -829,7 +859,19 @@ namespace Newtonsoft.Json /// <returns>A JSON string of the XNode.</returns>
public static string SerializeXNode(XObject node, Formatting formatting)
{
- XmlNodeConverter converter = new XmlNodeConverter();
+ return SerializeXNode(node, formatting, false);
+ }
+
+ /// <summary>
+ /// Serializes the <see cref="XNode"/> to a JSON string.
+ /// </summary>
+ /// <param name="node">The node to serialize.</param>
+ /// <param name="formatting">Indicates how the output is formatted.</param>
+ /// <param name="omitRootObject">Omits writing the root object.</param>
+ /// <returns>A JSON string of the XNode.</returns>
+ public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
+ {
+ XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
return SerializeObject(node, formatting, converter);
}
@@ -852,8 +894,24 @@ namespace Newtonsoft.Json /// <returns>The deserialized XNode</returns>
public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
{
+ return DeserializeXNode(value, deserializeRootElementName, false);
+ }
+
+ /// <summary>
+ /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root elment.
+ /// </summary>
+ /// <param name="value">The JSON string.</param>
+ /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+ /// <param name="writeArrayAttribute">
+ /// A flag to indicate whether to write the Json.NET array attribute.
+ /// This attribute helps preserve arrays when converting the written XML back to JSON.
+ /// </param>
+ /// <returns>The deserialized XNode</returns>
+ public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+ {
XmlNodeConverter converter = new XmlNodeConverter();
converter.DeserializeRootElementName = deserializeRootElementName;
+ converter.WriteArrayAttribute = writeArrayAttribute;
return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
}
|