using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Specialized;
using System.Web.Routing;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Web.SessionState;
using System.Xml.Serialization;
public string Name { get; set; }
public int Age { get; set; }
public object ExtraData { get; set; }
[XmlAnyElement("ExtraData")]
public XElement ExtraDataXml
return JsonExtensions.SerializeExtraDataXElement("ExtraData", ExtraData);
ExtraData = JsonExtensions.DeserializeExtraDataXElement("ExtraData", value);
public static class JsonExtensions
public static XElement SerializeExtraDataXElement(string name, object extraData)
var token = JToken.FromObject(extraData);
return new XElement(name, (string)token);
else if (token is JArray)
return new JObject(new JProperty(name, token)).ToXElement(false, name, true);
return token.ToXElement(false, name, true);
public static object DeserializeExtraDataXElement(string name, XElement element)
extraData = element.ToJToken(true, name, true);
if (extraData is JObject)
var obj = (JObject)extraData;
if (obj.Count == 1 && obj.Properties().First().Name == name)
extraData = obj.Properties().First().Value;
extraData = ((JValue)extraData).Value;
public static XElement ToXElement(this JToken obj, bool omitRootObject, string deserializeRootElementName, bool writeArrayAttribute)
using (var reader = obj.CreateReader())
var converter = new Newtonsoft.Json.Converters.XmlNodeConverter() { OmitRootObject = omitRootObject, DeserializeRootElementName = deserializeRootElementName, WriteArrayAttribute = writeArrayAttribute };
var jsonSerializer = JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = { converter } });
return jsonSerializer.Deserialize<XElement>(reader);
public static JToken ToJToken(this XElement xElement, bool omitRootObject, string deserializeRootElementName, bool writeArrayAttribute)
var settings = new JsonSerializerSettings { Converters = { new XmlNodeConverter { OmitRootObject = omitRootObject, DeserializeRootElementName = deserializeRootElementName, WriteArrayAttribute = writeArrayAttribute } } };
var root = JToken.FromObject(xElement, JsonSerializer.CreateDefault(settings));
""ExtraData"": [ ""hello"", ""there"" ]
public static void Test()
foreach (var json in new[] { GetJson1(), GetJson2(), GetJson3(), GetJson4() })
private static void Test(string json)
Console.WriteLine("Original JSON: ");
var person = JsonConvert.DeserializeObject<Person>(json);
var xml = person.GetXml(true);
Console.WriteLine("Deserialized and reserialized as XML:");
var person2 = xml.LoadFromXml<Person>();
var json2 = JsonConvert.SerializeObject(person2, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine("And then deserialized and reserialized as JSON:");
Console.WriteLine(json2);
if (JTokenComparer.Instance.Compare(Newtonsoft.Json.Linq.JToken.Parse(json), Newtonsoft.Json.Linq.JToken.Parse(json2)) != 0)
throw new InvalidOperationException("JTokenComparer.Instance.Compare(Newtonsoft.Json.Linq.JToken.Parse(json), Newtonsoft.Json.Linq.JToken.Parse(json2)) != 0");
Console.WriteLine("Original and re-serialized JSON are equivalent.");
public static void Main()
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName + "\n");
public static class XmlSerializationHelper
public static T LoadFromXml<T>(this string xmlString)
using (StringReader reader = new StringReader(xmlString))
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
public static string GetXml<T>(this T obj, bool omitStandardNamespaces = false)
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
ns = new XmlSerializerNamespaces();
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
public class JTokenComparer : IComparer<JToken>
public static JTokenComparer Instance { get { return instance; } }
static JTokenComparer instance;
instance = new JTokenComparer();
readonly Dictionary<Type, KeyValuePair<int, IComparer<JToken>>> dict;
dict = new Dictionary<Type, KeyValuePair<int, IComparer<JToken>>>
{typeof(JValue), new KeyValuePair<int, IComparer<JToken>>(0, new JValueComparer()) },
{typeof(JProperty), new KeyValuePair<int, IComparer<JToken>>(1, new JPropertyComparer()) },
{typeof(JArray), new KeyValuePair<int, IComparer<JToken>>(2, new JArrayComparer()) },
{typeof(JObject), new KeyValuePair<int, IComparer<JToken>>(3, new JObjectComparer()) },
{typeof(JConstructor), new KeyValuePair<int, IComparer<JToken>>(4, new JConstructorComparer()) },
#region IComparer<JToken> Members
public int Compare(JToken x, JToken y)
if (x is JRaw || y is JRaw)
throw new InvalidOperationException("Tokens of type JRaw cannot be sorted");
if (object.ReferenceEquals(x, y))
var typeData1 = dict[x.GetType()];
var typeData2 = dict[y.GetType()];
if ((comp = typeData1.Key.CompareTo(typeData2.Key)) != 0)
return JTokenComparerBase.ReturnComparison(comp);
if (typeData1.Value != typeData2.Value)
throw new InvalidOperationException("inconsistent dictionary values");
return typeData2.Value.Compare(x, y);
abstract class JTokenComparerBase
static void OnDifference(int comparison)
GC.KeepAlive(string.Empty);
protected internal static int ReturnComparison(int comparison)
OnDifference(comparison);
abstract class JTokenComparerBase<TJToken> : JTokenComparerBase, IComparer<JToken> where TJToken : JToken
protected TJToken CheckType(JToken item)
if (item != null && item.GetType() != typeof(TJToken))
throw new ArgumentException(string.Format("Actual type {0} of token \"{1}\" does not match expected type {2}", item.GetType(), item, typeof(TJToken)));
protected bool TryBaseCompare(TJToken x, TJToken y, out int comparison)
if (object.ReferenceEquals(x, y))
protected abstract int CompareDerived(TJToken x, TJToken y);
protected int TokenCompare(JToken x, JToken y)
if (TryBaseCompare(tx, ty, out comp))
return ReturnComparison(comp);
return CompareDerived(tx, ty);
#region IComparer<JToken> Members
int IComparer<JToken>.Compare(JToken x, JToken y)
return TokenCompare(x, y);
abstract class JContainerOrderedComparerBase<TJToken> : JTokenComparerBase<TJToken> where TJToken : JContainer
protected int CompareItemsInOrder(TJToken x, TJToken y)
for (int i = 0, n = Math.Min(x.Count, y.Count); i < n; i++)
if ((comp = JTokenComparer.Instance.Compare(x[i], y[i])) != 0)
return ReturnComparison(comp);
if ((comp = x.Count.CompareTo(y.Count)) != 0)
return ReturnComparison(comp);
return ReturnComparison(0);
class JPropertyComparer : JTokenComparerBase<JProperty>
protected override int CompareDerived(JProperty x, JProperty y)
if ((comp = x.Name.CompareTo(y.Name)) != 0)
return ReturnComparison(comp);
return JTokenComparer.Instance.Compare(x.Value, y.Value);
class JObjectComparer : JTokenComparerBase<JObject>
protected override int CompareDerived(JObject x, JObject y)
foreach (var propertyComp in x.Properties().OrderBy(p => p.Name).Zip(y.Properties().OrderBy(p => p.Name), (xp, yp) => JTokenComparer.Instance.Compare(xp, yp)))
if ((comp = x.Count.CompareTo(y.Count)) != 0)
return ReturnComparison(comp);
return ReturnComparison(0);
class JArrayComparer : JContainerOrderedComparerBase<JArray>
protected override int CompareDerived(JArray x, JArray y)
if ((comp = CompareItemsInOrder(x, y)) != 0)
return ReturnComparison(comp);
return ReturnComparison(0);
class JConstructorComparer : JContainerOrderedComparerBase<JConstructor>
protected override int CompareDerived(JConstructor x, JConstructor y)
if ((comp = x.Name.CompareTo(y.Name)) != 0)
return ReturnComparison(comp);
if ((comp = CompareItemsInOrder(x, y)) != 0)
return ReturnComparison(comp);
return ReturnComparison(0);
class JValueComparer : JTokenComparerBase<JValue>
protected override int CompareDerived(JValue x, JValue y)
return Comparer<JToken>.Default.Compare(x, y);