-When converting JSON to XML using XmlNodeConverter, changed special JSON properties ($id, $ref, $type) to be attributes rather than child elements
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#if !SILVERLIGHT
|
#if !SILVERLIGHT
|
||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json.Tests.Serialization;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -71,12 +72,19 @@ namespace Newtonsoft.Json.Tests.Converters
|
|||||||
}
|
}
|
||||||
|
|
||||||
private XmlNode DeserializeXmlNode(string json)
|
private XmlNode DeserializeXmlNode(string json)
|
||||||
|
{
|
||||||
|
return DeserializeXmlNode(json, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private XmlNode DeserializeXmlNode(string json, string deserializeRootElementName)
|
||||||
{
|
{
|
||||||
JsonTextReader reader;
|
JsonTextReader reader;
|
||||||
|
|
||||||
reader = new JsonTextReader(new StringReader(json));
|
reader = new JsonTextReader(new StringReader(json));
|
||||||
reader.Read();
|
reader.Read();
|
||||||
XmlNodeConverter converter = new XmlNodeConverter();
|
XmlNodeConverter converter = new XmlNodeConverter();
|
||||||
|
if (deserializeRootElementName != null)
|
||||||
|
converter.DeserializeRootElementName = deserializeRootElementName;
|
||||||
|
|
||||||
XmlNode node = (XmlNode)converter.ReadJson(reader, typeof (XmlDocument), new JsonSerializer());
|
XmlNode node = (XmlNode)converter.ReadJson(reader, typeof (XmlDocument), new JsonSerializer());
|
||||||
|
|
||||||
@@ -848,6 +856,56 @@ namespace Newtonsoft.Json.Tests.Converters
|
|||||||
</person>
|
</person>
|
||||||
</root>".Replace(Environment.NewLine, string.Empty), doc.InnerXml);
|
</root>".Replace(Environment.NewLine, string.Empty), doc.InnerXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SerializeDeserializeSpecialProperties()
|
||||||
|
{
|
||||||
|
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 });
|
||||||
|
|
||||||
|
Assert.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>";
|
||||||
|
|
||||||
|
Assert.AreEqual(expected, xml);
|
||||||
|
|
||||||
|
string xmlJson = SerializeXmlNode(node);
|
||||||
|
string expectedXmlJson = @"{
|
||||||
|
""root"": {
|
||||||
|
""$id"": ""1"",
|
||||||
|
""other"": {
|
||||||
|
""$id"": ""2"",
|
||||||
|
""blah"": null
|
||||||
|
},
|
||||||
|
""self"": {
|
||||||
|
""$ref"": ""1""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedXmlJson, xmlJson);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2939,5 +2939,82 @@ keyword such as type of business.""
|
|||||||
Assert.AreEqual(testObject.Document.InnerXml, newTestObject.Document.InnerXml);
|
Assert.AreEqual(testObject.Document.InnerXml, newTestObject.Document.InnerXml);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FullClientMapSerialization()
|
||||||
|
{
|
||||||
|
ClientMap source = new ClientMap()
|
||||||
|
{
|
||||||
|
position = new Pos() { X = 100, Y = 200 },
|
||||||
|
center = new PosDouble() { X = 251.6, Y = 361.3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonConvert.SerializeObject(source, new PosConverter(), new PosDoubleConverter());
|
||||||
|
Assert.AreEqual("{\"position\":new Pos(100,200),\"center\":new PosD(251.6,361.3)}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClientMap
|
||||||
|
{
|
||||||
|
public Pos position { get; set; }
|
||||||
|
public PosDouble center { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Pos
|
||||||
|
{
|
||||||
|
public int X { get; set; }
|
||||||
|
public int Y { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PosDouble
|
||||||
|
{
|
||||||
|
public double X { get; set; }
|
||||||
|
public double Y { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PosConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
Pos p = (Pos)value;
|
||||||
|
|
||||||
|
if (p != null)
|
||||||
|
writer.WriteRawValue(String.Format("new Pos({0},{1})", p.X, p.Y));
|
||||||
|
else
|
||||||
|
writer.WriteNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType.IsAssignableFrom(typeof(Pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PosDoubleConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
PosDouble p = (PosDouble)value;
|
||||||
|
|
||||||
|
if (p != null)
|
||||||
|
writer.WriteRawValue(String.Format("new PosD({0},{1})", p.X, p.Y));
|
||||||
|
else
|
||||||
|
writer.WriteNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType.IsAssignableFrom(typeof(PosDouble));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -820,7 +820,10 @@ namespace Newtonsoft.Json.Converters
|
|||||||
switch (node.NodeType)
|
switch (node.NodeType)
|
||||||
{
|
{
|
||||||
case XmlNodeType.Attribute:
|
case XmlNodeType.Attribute:
|
||||||
return "@" + ResolveFullName(node, manager);
|
if (node.NamespaceURI == JsonNamespaceUri)
|
||||||
|
return "$" + node.LocalName;
|
||||||
|
else
|
||||||
|
return "@" + ResolveFullName(node, manager);
|
||||||
case XmlNodeType.CDATA:
|
case XmlNodeType.CDATA:
|
||||||
return CDataName;
|
return CDataName;
|
||||||
case XmlNodeType.Comment:
|
case XmlNodeType.Comment:
|
||||||
@@ -966,9 +969,13 @@ namespace Newtonsoft.Json.Converters
|
|||||||
case XmlNodeType.Whitespace:
|
case XmlNodeType.Whitespace:
|
||||||
case XmlNodeType.SignificantWhitespace:
|
case XmlNodeType.SignificantWhitespace:
|
||||||
if (node.NamespaceURI == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
|
if (node.NamespaceURI == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
|
||||||
break;
|
return;
|
||||||
else if (node.NamespaceURI == JsonNamespaceUri)
|
|
||||||
break;
|
if (node.NamespaceURI == JsonNamespaceUri)
|
||||||
|
{
|
||||||
|
if (node.LocalName == "Array")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (writePropertyName)
|
if (writePropertyName)
|
||||||
writer.WritePropertyName(GetPropertyName(node, manager));
|
writer.WritePropertyName(GetPropertyName(node, manager));
|
||||||
@@ -1042,18 +1049,20 @@ namespace Newtonsoft.Json.Converters
|
|||||||
throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
|
throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(DeserializeRootElementName))
|
|
||||||
{
|
|
||||||
rootNode = document.CreateElement(DeserializeRootElementName);
|
|
||||||
document.AppendChild(rootNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reader.TokenType != JsonToken.StartObject)
|
if (reader.TokenType != JsonToken.StartObject)
|
||||||
throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
|
throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
|
||||||
|
|
||||||
reader.Read();
|
if (!string.IsNullOrEmpty(DeserializeRootElementName))
|
||||||
|
{
|
||||||
DeserializeNode(reader, document, manager, rootNode);
|
//rootNode = document.CreateElement(DeserializeRootElementName);
|
||||||
|
//document.AppendChild(rootNode);
|
||||||
|
ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
DeserializeNode(reader, document, manager, rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
#if !NET20
|
#if !NET20
|
||||||
if (objectType == typeof(XElement))
|
if (objectType == typeof(XElement))
|
||||||
@@ -1088,169 +1097,217 @@ namespace Newtonsoft.Json.Converters
|
|||||||
// processing instructions and the xml declaration start with ?
|
// processing instructions and the xml declaration start with ?
|
||||||
if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
|
if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
|
||||||
{
|
{
|
||||||
if (propertyName == DeclarationName)
|
CreateInstruction(reader, document, currentNode, propertyName);
|
||||||
{
|
|
||||||
string version = null;
|
|
||||||
string encoding = null;
|
|
||||||
string standalone = null;
|
|
||||||
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
|
|
||||||
{
|
|
||||||
switch (reader.Value.ToString())
|
|
||||||
{
|
|
||||||
case "@version":
|
|
||||||
reader.Read();
|
|
||||||
version = reader.Value.ToString();
|
|
||||||
break;
|
|
||||||
case "@encoding":
|
|
||||||
reader.Read();
|
|
||||||
encoding = reader.Value.ToString();
|
|
||||||
break;
|
|
||||||
case "@standalone":
|
|
||||||
reader.Read();
|
|
||||||
standalone = reader.Value.ToString();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
|
|
||||||
currentNode.AppendChild(declaration);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
|
|
||||||
currentNode.AppendChild(instruction);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// deserialize xml element
|
|
||||||
bool finishedAttributes = false;
|
|
||||||
bool finishedElement = false;
|
|
||||||
string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
|
|
||||||
|
|
||||||
Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
if (reader.TokenType == JsonToken.StartArray)
|
if (reader.TokenType == JsonToken.StartArray)
|
||||||
{
|
{
|
||||||
IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
|
ReadArrayElements(reader, document, propertyName, currentNode, manager);
|
||||||
|
|
||||||
currentNode.AppendChild(nestedArrayElement);
|
|
||||||
|
|
||||||
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
|
|
||||||
{
|
|
||||||
DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// a string token means the element only has a single text child
|
|
||||||
if (reader.TokenType != JsonToken.String
|
|
||||||
&& reader.TokenType != JsonToken.Null
|
|
||||||
&& reader.TokenType != JsonToken.Boolean
|
|
||||||
&& reader.TokenType != JsonToken.Integer
|
|
||||||
&& reader.TokenType != JsonToken.Float
|
|
||||||
&& reader.TokenType != JsonToken.Date
|
|
||||||
&& reader.TokenType != JsonToken.StartConstructor)
|
|
||||||
{
|
|
||||||
// read properties until first non-attribute is encountered
|
|
||||||
while (!finishedAttributes && !finishedElement && reader.Read())
|
|
||||||
{
|
|
||||||
switch (reader.TokenType)
|
|
||||||
{
|
|
||||||
case JsonToken.PropertyName:
|
|
||||||
string attributeName = reader.Value.ToString();
|
|
||||||
|
|
||||||
if (attributeName[0] == '@')
|
|
||||||
{
|
|
||||||
attributeName = attributeName.Substring(1);
|
|
||||||
reader.Read();
|
|
||||||
string attributeValue = reader.Value.ToString();
|
|
||||||
attributeNameValues.Add(attributeName, attributeValue);
|
|
||||||
|
|
||||||
string namespacePrefix;
|
|
||||||
|
|
||||||
if (IsNamespaceAttribute(attributeName, out namespacePrefix))
|
|
||||||
{
|
|
||||||
manager.AddNamespace(namespacePrefix, attributeValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
finishedAttributes = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JsonToken.EndObject:
|
|
||||||
finishedElement = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// have to wait until attributes have been parsed before creating element
|
// have to wait until attributes have been parsed before creating element
|
||||||
// attributes may contain namespace info used by the element
|
// attributes may contain namespace info used by the element
|
||||||
IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
|
ReadElement(reader, document, currentNode, propertyName, manager);
|
||||||
|
|
||||||
currentNode.AppendChild(element);
|
|
||||||
|
|
||||||
// add attributes to newly created element
|
|
||||||
foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
|
|
||||||
{
|
|
||||||
string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
|
|
||||||
|
|
||||||
IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
|
|
||||||
? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
|
|
||||||
: document.CreateAttribute(nameValue.Key, nameValue.Value);
|
|
||||||
|
|
||||||
element.SetAttributeNode(attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reader.TokenType == JsonToken.String)
|
|
||||||
{
|
|
||||||
element.AppendChild(document.CreateTextNode(reader.Value.ToString()));
|
|
||||||
}
|
|
||||||
else if (reader.TokenType == JsonToken.Integer)
|
|
||||||
{
|
|
||||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((long)reader.Value)));
|
|
||||||
}
|
|
||||||
else if (reader.TokenType == JsonToken.Float)
|
|
||||||
{
|
|
||||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((double)reader.Value)));
|
|
||||||
}
|
|
||||||
else if (reader.TokenType == JsonToken.Boolean)
|
|
||||||
{
|
|
||||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((bool)reader.Value)));
|
|
||||||
}
|
|
||||||
else if (reader.TokenType == JsonToken.Date)
|
|
||||||
{
|
|
||||||
DateTime d = (DateTime)reader.Value;
|
|
||||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind))));
|
|
||||||
}
|
|
||||||
else if (reader.TokenType == JsonToken.Null)
|
|
||||||
{
|
|
||||||
// empty element. do nothing
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// finished element will have no children to deserialize
|
|
||||||
if (!finishedElement)
|
|
||||||
{
|
|
||||||
manager.PushScope();
|
|
||||||
|
|
||||||
DeserializeNode(reader, document, manager, element);
|
|
||||||
|
|
||||||
manager.PopScope();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> attributeNameValues = ReadAttributeElements(reader, manager);
|
||||||
|
|
||||||
|
string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
|
||||||
|
|
||||||
|
IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
|
||||||
|
|
||||||
|
currentNode.AppendChild(element);
|
||||||
|
|
||||||
|
// add attributes to newly created element
|
||||||
|
foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
|
||||||
|
{
|
||||||
|
string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
|
||||||
|
|
||||||
|
IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
|
||||||
|
? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
|
||||||
|
: document.CreateAttribute(nameValue.Key, nameValue.Value);
|
||||||
|
|
||||||
|
element.SetAttributeNode(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonToken.String)
|
||||||
|
{
|
||||||
|
element.AppendChild(document.CreateTextNode(reader.Value.ToString()));
|
||||||
|
}
|
||||||
|
else if (reader.TokenType == JsonToken.Integer)
|
||||||
|
{
|
||||||
|
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((long)reader.Value)));
|
||||||
|
}
|
||||||
|
else if (reader.TokenType == JsonToken.Float)
|
||||||
|
{
|
||||||
|
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((double)reader.Value)));
|
||||||
|
}
|
||||||
|
else if (reader.TokenType == JsonToken.Boolean)
|
||||||
|
{
|
||||||
|
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((bool)reader.Value)));
|
||||||
|
}
|
||||||
|
else if (reader.TokenType == JsonToken.Date)
|
||||||
|
{
|
||||||
|
DateTime d = (DateTime)reader.Value;
|
||||||
|
element.AppendChild(document.CreateTextNode(XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind))));
|
||||||
|
}
|
||||||
|
else if (reader.TokenType == JsonToken.Null)
|
||||||
|
{
|
||||||
|
// empty element. do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// finished element will have no children to deserialize
|
||||||
|
if (reader.TokenType != JsonToken.EndObject)
|
||||||
|
{
|
||||||
|
manager.PushScope();
|
||||||
|
|
||||||
|
DeserializeNode(reader, document, manager, element);
|
||||||
|
|
||||||
|
manager.PopScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
|
||||||
|
{
|
||||||
|
string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
|
||||||
|
|
||||||
|
IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
|
||||||
|
|
||||||
|
currentNode.AppendChild(nestedArrayElement);
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
|
||||||
|
{
|
||||||
|
DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
|
||||||
|
bool finishedAttributes = false;
|
||||||
|
bool finishedElement = false;
|
||||||
|
|
||||||
|
// a string token means the element only has a single text child
|
||||||
|
if (reader.TokenType != JsonToken.String
|
||||||
|
&& reader.TokenType != JsonToken.Null
|
||||||
|
&& reader.TokenType != JsonToken.Boolean
|
||||||
|
&& reader.TokenType != JsonToken.Integer
|
||||||
|
&& reader.TokenType != JsonToken.Float
|
||||||
|
&& reader.TokenType != JsonToken.Date
|
||||||
|
&& reader.TokenType != JsonToken.StartConstructor)
|
||||||
|
{
|
||||||
|
// read properties until first non-attribute is encountered
|
||||||
|
while (!finishedAttributes && !finishedElement && reader.Read())
|
||||||
|
{
|
||||||
|
switch (reader.TokenType)
|
||||||
|
{
|
||||||
|
case JsonToken.PropertyName:
|
||||||
|
string attributeName = reader.Value.ToString();
|
||||||
|
string attributeValue;
|
||||||
|
char firstChar = attributeName[0];
|
||||||
|
|
||||||
|
switch (firstChar)
|
||||||
|
{
|
||||||
|
case '@':
|
||||||
|
attributeName = attributeName.Substring(1);
|
||||||
|
reader.Read();
|
||||||
|
attributeValue = reader.Value.ToString();
|
||||||
|
attributeNameValues.Add(attributeName, attributeValue);
|
||||||
|
|
||||||
|
string namespacePrefix;
|
||||||
|
if (IsNamespaceAttribute(attributeName, out namespacePrefix))
|
||||||
|
{
|
||||||
|
manager.AddNamespace(namespacePrefix, attributeValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
attributeName = attributeName.Substring(1);
|
||||||
|
reader.Read();
|
||||||
|
attributeValue = reader.Value.ToString();
|
||||||
|
|
||||||
|
// check that JsonNamespaceUri is in scope
|
||||||
|
// if it isn't then add it to document and namespace manager
|
||||||
|
string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri);
|
||||||
|
if (jsonPrefix == null)
|
||||||
|
{
|
||||||
|
// ensure that the prefix used is free
|
||||||
|
int? i = null;
|
||||||
|
while (manager.LookupNamespace("json" + i) != null)
|
||||||
|
{
|
||||||
|
i = i.GetValueOrDefault() + 1;
|
||||||
|
}
|
||||||
|
jsonPrefix = "json" + i;
|
||||||
|
|
||||||
|
attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri);
|
||||||
|
manager.AddNamespace(jsonPrefix, JsonNamespaceUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
finishedAttributes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JsonToken.EndObject:
|
||||||
|
finishedElement = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributeNameValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
|
||||||
|
{
|
||||||
|
if (propertyName == DeclarationName)
|
||||||
|
{
|
||||||
|
string version = null;
|
||||||
|
string encoding = null;
|
||||||
|
string standalone = null;
|
||||||
|
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
|
||||||
|
{
|
||||||
|
switch (reader.Value.ToString())
|
||||||
|
{
|
||||||
|
case "@version":
|
||||||
|
reader.Read();
|
||||||
|
version = reader.Value.ToString();
|
||||||
|
break;
|
||||||
|
case "@encoding":
|
||||||
|
reader.Read();
|
||||||
|
encoding = reader.Value.ToString();
|
||||||
|
break;
|
||||||
|
case "@standalone":
|
||||||
|
reader.Read();
|
||||||
|
standalone = reader.Value.ToString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
|
||||||
|
currentNode.AppendChild(declaration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
|
||||||
|
currentNode.AppendChild(instruction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
|
private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
|
||||||
{
|
{
|
||||||
return (!string.IsNullOrEmpty(elementPrefix))
|
return (!string.IsNullOrEmpty(elementPrefix))
|
||||||
|
|||||||
Reference in New Issue
Block a user