questions/47993392/alternative-for-deserializing-xml-with-xmlserializer

CSharp · Console

/Program.cs

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");
        }
    }
;