Click here to Skip to main content
15,886,724 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
using (StreamWriter file = File.CreateText(@"c:\test\source.json"))
           {
             JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(file, eList);
           }


I use this to write my JSON Object to a json file. But is it easy with some similar code to write the Object to XML instead?

Thanks in advanced

What I have tried:

looked for an alternative for Newtonsoft.Json
Posted
Updated 14-Mar-17 4:39am

The answer is yes and no. It depends on how the data is to be serialized.

I have two Converter classes, one for JSON & one for XML. Both are called the same way, so easy to switch.

I'll post both below. The XML version has additional information that should be self-explanatory.

JSON using NewtownSoft lib


C#
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;

namespace DotNet.Shared.Helpers
{
    public static class JsonConverter
    {
        public static string FromClass<T>(T data, bool isEmptyToNull = false, JsonSerializerSettings jsonSettings = null)
        {
            string response = string.Empty;

            if (!EqualityComparer<T>.Default.Equals(data, default(T)))
                response = JsonConvert.SerializeObject(data, jsonSettings);

            return isEmptyToNull ? (response == "{}" ? "null" : response) : response;
        }

        public static MemoryStream FromClassToStream<T>(T data, StreamWriter writer, bool isEmptyToNull = false, JsonSerializerSettings jsonSettings = null)
        {
            var stream = new MemoryStream();

            if (!EqualityComparer<T>.Default.Equals(data, default(T)))
            {
                writer = new StreamWriter(stream);
                writer.Write(FromClass(data, isEmptyToNull, jsonSettings));
                writer.Flush();
                stream.Position = 0;
            }
            return stream;
        }

        public static T ToClass<T>(string data, JsonSerializerSettings jsonSettings = null)
        {
            var response = default(T);

            if (!string.IsNullOrEmpty(data))
                response = jsonSettings == null 
                    ? JsonConvert.DeserializeObject<T>(data) 
                    : JsonConvert.DeserializeObject<T>(data, jsonSettings);

                return response;
        }

        public static T ToClassFromStream<T>(MemoryStream stream)
        {
            var response = default(T);

            if (stream != null)
            {
                using (var reader = new StreamReader(stream))
                    using (var jsonReader = new JsonTextReader(reader))
                        response = (new JsonSerializer()).Deserialize<T>(jsonReader);
            }
            return response;
        }
    }
}

XML using Microsoft Libs


C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace WorkingWithXml
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new XmlRootClass
            {
                Id = 12345567890123456789,
                Title = "Widget",
                Amount = new AmountType { Value = 123.45, CurrencyID = CurrencyCodeType.USD },
                Description = new CData("This is a description with embedded html"),
            };

            var raw = XmlConverter.FromClass(data);

            var newData = XmlConverter.ToClass<XmlRootClass>(raw);

            Debugger.Break();
        }
    }


    // Naming a root element
    [XmlRoot(ElementName = "Product", IsNullable = false)]
    public class XmlRootClass
    {
        [XmlElement("id123)")]
        public ulong Id { get; set; }
        public string Title { get; set; }

        // a value type element with an attribute
        [XmlElement("amt")]
        public AmountType Amount { get; set; }

        // Custom element data format
        [XmlElement("description", typeof(CData))]
        public CData Description { get; set; }

        // example of optional serialization
        [XmlElement, DefaultValue(false)]
        public bool IsAvailable { get; set; }

    }

    public class AmountType
    {
        [XmlText]
        public double Value { get; set; }

        //enum type attribute (same works with an XmlElement)
        [XmlAttribute("currencyID")]
        public string CurrencyID_intern { get; set; }
        [XmlIgnore]
        public CurrencyCodeType? CurrencyID
        {
            get
            {
                return CurrencyID_intern.StringToEnum<CurrencyCodeType?>
                  (CurrencyCodeType.CustomCode, isNullable: true);
            }
            set { CurrencyID_intern = value.ToString(); }
        }
    }

    public enum CurrencyCodeType
    {
        CustomCode, // missing from list
        AUD,        // Australia dollar
        JPY,        // Japanese yen
        USD,        // US dollar
    }

    public static class EnumExtensions
    {
        public static T StringToEnum<T>(this string input, T defaultValue = default(T), bool isNullable = false)
        {
            T outType;
            if (string.IsNullOrEmpty(input) &&
                isNullable &&
                Nullable.GetUnderlyingType(typeof(T)) != null &&
                Nullable.GetUnderlyingType(typeof(T)).GetElementType() == null)
                return default(T);
            return input.EnumTryParse(out outType) ? outType : defaultValue;
        }

        public static bool EnumTryParse<T>(this string input, out T theEnum)
        {
            Type type = Nullable.GetUnderlyingType(typeof(T)) != null ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T);

            foreach (string en in Enum.GetNames(type))
                if (en.Equals(input, StringComparison.CurrentCultureIgnoreCase))
                {
                    theEnum = (T)Enum.Parse(type, input, true);
                    return true;
                }
            theEnum = default(T);
            return false;
        }
    }

    public static class XmlConverter
    {
        public static string FromClass<T>(T data, XmlSerializerNamespaces ns = null)
        {
            string response = string.Empty;

            var ms = new MemoryStream();
            try
            {
                ms = FromClassToStream(data, ns);

                if (ms != null)
                {
                    ms.Position = 0;
                    using (var sr = new StreamReader(ms))
                        response = sr.ReadToEnd();
                }

            }
            finally
            {
                // don't want memory leaks...
                ms.Flush();
                ms.Dispose();
                ms = null;
            }

            return response;
        }

        public static MemoryStream FromClassToStream<T>(T data, XmlSerializerNamespaces ns = null)
        {
            var stream = default(MemoryStream);

            if (!EqualityComparer<T>.Default.Equals(data, default(T)))
            {
                var settings = new XmlWriterSettings()
                {
                    Encoding = Encoding.UTF8,
                    Indent = true,
                    ConformanceLevel = ConformanceLevel.Auto,
                    CheckCharacters = true,
                    OmitXmlDeclaration = false
                };

                XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));

                stream = new MemoryStream();
                using (XmlWriter writer = XmlWriter.Create(stream, settings))
                {
                    serializer.Serialize(writer, data, ns);
                    writer.Flush();
                }
                stream.Position = 0;
            }
            return stream;
        }

        public static T ToClass<T>(string data)
        {
            var response = default(T);

            if (!string.IsNullOrEmpty(data))
            {
                var settings = new XmlReaderSettings() { IgnoreWhitespace = true };

                XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));

                XmlReader reader = XmlReader.Create(new StringReader(data), settings);
                response = (T)Convert.ChangeType(serializer.Deserialize(reader), typeof(T));
            }
            return response;
        }
    }

    // ref: http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor/39642834#39642834
    public static class XmlSerializerFactoryNoThrow
    {
        public static Dictionary<Type, XmlSerializer> cache = new Dictionary<Type, XmlSerializer>();

        private static object SyncRootCache = new object();

        public static XmlSerializer Create(Type type)
        {
            XmlSerializer serializer;

            lock (SyncRootCache)
                if (cache.TryGetValue(type, out serializer))
                    return serializer;

            lock (type) //multiple variable of type of one type is same instance
            {
                //constructor XmlSerializer.FromTypes does not throw the first chance exception           
                serializer = XmlSerializer.FromTypes(new[] { type })[0];
            }

            lock (SyncRootCache) cache[type] = serializer;
            return serializer;
        }
    }

    // ref: http://codercorner.blogspot.com.au/2006/11/serialization-and-cdata.html
    public class CData : IXmlSerializable
    {
        public CData()
        { }

        public CData(string text)
        {
            this.text = text;
        }

        private string text;
        public string Text => text;

        XmlSchema IXmlSerializable.GetSchema() => null;

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            text = reader.ReadElementContentAsString();
            reader.Read(); // without this line, you will lose value of all other fields
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteCData(text);
        }

        public override string ToString() => text;
    }
}
 
Share this answer
 
v2
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(eList.GetType());

using (StreamWriter file = File.CreateText(@"c:\test\source.xml"))
{
    ser.Serialize(file, eList);
}


You can also use DataContractSerializer

DataContractSerializer Class (System.Runtime.Serialization)[^]
 
Share this answer
 
Comments
Graeme_Grant 14-Mar-17 11:07am    
I do mention that in my answer. Just wrap it up in a helper class with some extra handling. ;)

Hide   Copy Code
XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));


My point was that XML is a little bit more bulky than Json.
Amien90 14-Mar-17 12:04pm    
@F-ES Sitecore. . i'm getting this Error:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll

Additional information: There was an error reflecting type 'System.Collections.Generic.List`1[JsonSchema.RootJson]'.
F-ES Sitecore 14-Mar-17 12:16pm    
You might have properties on the object that aren't serialisable. Make sure the class is marked as serializable and you might need a process of elimination to work out what properties have a problem, but the exception details may give you a clue

http://stackoverflow.com/questions/60573/xmlserializer-there-was-an-error-reflecting-type

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900