How to convert XML to JSON using C#/LINQ?

前端 未结 3 1115
感情败类
感情败类 2020-11-30 01:52

I have the following XML file that I need to convert to JSON in the server. Initially I thought I would convert it to a Dictionary and then use the JavaScriptSerializer to t

相关标签:
3条回答
  • 2020-11-30 02:26

    For deep nesting of XML elements with more and unknown attributes you can use this recursion:

    private static string XmlToJson(string xmlString)
    {
        return new JavaScriptSerializer().Serialize(GetXmlValues(XElement.Parse(xmlString)));
    }
    
    private static Dictionary<string, object> GetXmlValues(XElement xml)
    {
        var attr = xml.Attributes().ToDictionary(d => d.Name.LocalName, d => (object)d.Value);
        if (xml.HasElements) attr.Add("_value", xml.Elements().Select(e => GetXmlValues(e)));
        else if (!xml.IsEmpty) attr.Add("_value", xml.Value);
    
        return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
    }
    

    For your example the result will be:

    {
        "Columns":{
            "_value":[
                {
                    "Column":{
                        "Name":"key1",
                        "DataType":"Boolean",
                        "_value":"True"
                    }
                },
                {
                    "Column":{
                        "Name":"key2",
                        "DataType":"String",
                        "_value":"Hello World"
                    }
                },
                {
                    "Column":{
                        "Name":"key3",
                        "DataType":"Integer",
                        "_value":"999"
                    }
                }
            ]
        }
    }
    

    And for more complex XML case like this, you can check the JSON analogue here.

    0 讨论(0)
  • 2020-11-30 02:29
    using System;
    using System.Linq;
    using System.Web.Script.Serialization;
    using System.Xml.Linq;
    
    class Program
    {
        static void Main()
        {
            var xml = 
            @"<Columns>
              <Column Name=""key1"" DataType=""Boolean"">True</Column>
              <Column Name=""key2"" DataType=""String"">Hello World</Column>
              <Column Name=""key3"" DataType=""Integer"">999</Column>
            </Columns>";
            var dic = XDocument
                .Parse(xml)
                .Descendants("Column")
                .ToDictionary(
                    c => c.Attribute("Name").Value, 
                    c => c.Value
                );
            var json = new JavaScriptSerializer().Serialize(dic);
            Console.WriteLine(json);
        }
    }
    

    produces:

    {"key1":"True","key2":"Hello World","key3":"999"}
    

    Obviously this treats all the values as strings. If you want to keep the underlying type semantics you could do the following:

    using System;
    using System.Linq;
    using System.Web.Script.Serialization;
    using System.Xml.Linq;
    
    class Program
    {
        static void Main()
        {
            var xml = 
            @"<Columns>
              <Column Name=""key1"" DataType=""System.Boolean"">True</Column>
              <Column Name=""key2"" DataType=""System.String"">Hello World</Column>
              <Column Name=""key3"" DataType=""System.Int32"">999</Column>
            </Columns>";
            var dic = XDocument
                .Parse(xml)
                .Descendants("Column")
                .ToDictionary(
                    c => c.Attribute("Name").Value, 
                    c => Convert.ChangeType(
                        c.Value,
                        typeof(string).Assembly.GetType(c.Attribute("DataType").Value, true)
                    )
                );
            var json = new JavaScriptSerializer().Serialize(dic);
            Console.WriteLine(json);
        }
    }
    

    produces:

    {"key1":true,"key2":"Hello World","key3":999}
    

    And if you cannot modify the underlying XML structure you will need a custom function that will convert between your custom types and the underlying .NET type:

    using System;
    using System.Linq;
    using System.Web.Script.Serialization;
    using System.Xml.Linq;
    
    class Program
    {
        static void Main()
        {
            var xml = 
            @"<Columns>
              <Column Name=""key1"" DataType=""Boolean"">True</Column>
              <Column Name=""key2"" DataType=""String"">Hello World</Column>
              <Column Name=""key3"" DataType=""Integer"">999</Column>
            </Columns>";
            var dic = XDocument
                .Parse(xml)
                .Descendants("Column")
                .ToDictionary(
                    c => c.Attribute("Name").Value, 
                    c => Convert.ChangeType(
                        c.Value, 
                        GetType(c.Attribute("DataType").Value)
                    )
                );
            var json = new JavaScriptSerializer().Serialize(dic);
            Console.WriteLine(json);
        }
    
        private static Type GetType(string type)
        {
            switch (type)
            {
                case "Integer":
                    return typeof(int);
                case "String":
                    return typeof(string);
                case "Boolean":
                    return typeof(bool);
                // TODO: add any other types that you want to support
                default:
                    throw new NotSupportedException(
                        string.Format("The type {0} is not supported", type)
                    );
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 02:30

    Is it necessary to use LINQ? Otherwise you can try this:

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);
    string jsonText = JsonConvert.SerializeXmlNode(doc);
    

    Taken from this post.

    0 讨论(0)
提交回复
热议问题