CSharp · Console
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters;
using System.IO;
using System.Data;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
// // https://stackoverflow.com/questions/47993392/alternative-for-deserializing-xml-with-xmlserializer/47999622#47999622
public class RootObject
{
[JsonConverter(typeof(SingleOrArrayConverter<Element>))]
public List<Element> Element { get; set; }
}
public class Element
{
[XmlAttribute]
[JsonProperty("@Name")]
public string Name { get; set; }
[XmlElement("SubElement")]
[JsonProperty("SubElement")]
[JsonConverter(typeof(SingleOrArrayConverter<SubElement>))]
public List<SubElement> _subelement { get; set; }
}
public class SubElement
{
[XmlElement("Color")]
[JsonConverter(typeof(SingleOrArrayConverter<string>))]
public List<string> Color { get; set; }
[XmlAttribute("Name")]
[JsonProperty("@Name")]
public string Name { get; set; }
}
public class TestClass
{
public static void Test()
{
var xmlString = GetXml();
Console.WriteLine("\nInput XML: ");
Console.WriteLine(xmlString);
var doc = XDocument.Parse(xmlString);
// Convert the XDocument to an intermediate JToken hierarchy.
var converter = new Newtonsoft.Json.Converters.XmlNodeConverter { OmitRootObject = true };
var rootToken = JObject.FromObject(doc, JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = { converter } }));
// Convert the JTOken to a RootObject
var rootObj = rootToken.ToObject<RootObject>();
Console.WriteLine("\nDeserialized {0} reserialized to JSON: ", rootObj);
Console.WriteLine(JsonConvert.SerializeObject(rootToken, Newtonsoft.Json.Formatting.Indented));
}
static string GetXml()
{
var xml = @"<List>
<Element Name=""A"">
<SubElement Name=""A1"">
<Color> Blue </Color>
<Color> Red </Color>
</SubElement>
<SubElement Name=""A2"">
<Color> Blue </Color>
<Color> Green </Color>
</SubElement>
</Element>
<Element Name=""B"">
<SubElement Name=""B1"">
<Color> Yellow </Color>
<Color> Red </Color>
</SubElement>
<SubElement Name=""B2"">
<Color> Yellow </Color>
<Color> Green </Color>
</SubElement>
</Element>
<Element Name=""C"">
<SubElement Name=""C1"">
<Color> Purple </Color>
<Color> Red </Color>
</SubElement>
<SubElement Name=""C2"">
<Color> Purple </Color>
<Color> Green </Color>
</SubElement>
</Element>
<Element Name=""D""/>
<Element Name=""E"">
<SubElement Name=""E1"">
<Color> Purple </Color>
</SubElement>
</Element>
</List>";
return xml;
}
}
class SingleOrArrayConverter<T> : JsonConverter
{
// Taken from
// https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n
// https://stackoverflow.com/a/18997172
// by Brian Rogers
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine();
try
{
TestClass.Test();
}
catch (Exception ex)
{
Console.WriteLine("Failed with unhandled exception: ");
Console.WriteLine(ex);
throw;
}
}
}
public class AssertionFailedException : System.Exception
{
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
}
public static class Assert
{
public static void IsTrue(bool value)
{
IsTrue(value, "failed");
}
public static void IsTrue(bool value, string message)
{
if (value == false)
throw new AssertionFailedException(message ?? "failed");
}
}