如何使用 C#/LINQ 将 XML 转换为 JSON?

Posted

技术标签:

【中文标题】如何使用 C#/LINQ 将 XML 转换为 JSON?【英文标题】:How to convert XML to JSON using C#/LINQ? 【发布时间】:2012-08-15 17:59:01 【问题描述】:

我有以下需要在服务器中转换为 JSON 的 XML 文件。最初我以为我会将它转换为字典,然后使用 javascriptSerializer 将其转换为 JSON,但由于每列可能有不同的值类型,我认为它不会起作用。以前有人在 C#/LINQ 中做过类似的事情吗?

我需要保留每列的值类型(布尔值、字符串、整数)。

如果我刚刚开始使用 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>

【问题讨论】:

需要保留DataType的值吗?如果不是,它可以转换成一个简单的关联数组。 是的,我需要保留数据类型,否则我只会将其转换为字典! How to convert JSON to XML or XML to JSON?的可能重复 【参考方案1】:
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);
    

产生:

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

显然,这会将所有值都视为字符串。如果您想保留底层类型语义,您可以执行以下操作:

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

产生:

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

如果您无法修改底层 XML 结构,您将需要一个自定义函数,该函数将在您的自定义类型和底层 .NET 类型之间进行转换:

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

【讨论】:

嗨,这会保留列的值类型吗? 真正的好:D,谢谢! 是的,第二种和第三种方法将保留值类型。 供参考,需要参考“System.Web.Extensions.dll”供JavaScriptSerializer解析。【参考方案2】:

有必要使用 LINQ 吗?否则你可以试试这个:

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

取自this post。

【讨论】:

不,但是 LINQ 更酷,我正在尝试学习新东西,顺便说一句,这会保留列的数据类型吗? 我自己没用过,不过也许我可以稍后测试一下,告诉你数据类型是否保留。【参考方案3】:

对于具有更多未知属性的 XML 元素的深层嵌套,您可以使用此递归:

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  ;

对于您的示例,结果将是:


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

对于更复杂的 XML 案例,如 this,您可以查看 JSON 模拟 here。

【讨论】:

以上是关于如何使用 C#/LINQ 将 XML 转换为 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

将 XmlNode 转换为 XNode?

如何将 SQL 中的多个内部联接转换为 LINQ?

如何使用 linq 将“Y”或“N”值转换为布尔值?

csharp 使用LINQ 2 XML将XML数据条目解析为C#对象的简单示例

具有XPath查询的SQL到LINQ转换

如何使用 SUM 计算将 SQL 转换为 Linq