如何将JSON转换为XML或XML转换为JSON?

Dav*_*.ca 270 c# xml json json.net

我开始使用Json.NET将JSON格式的字符串转换为object或反之.我不确定在Json.NET框架中,是否可以将JSON中的字符串转换为XML格式,反之亦然?

Dav*_*own 416

是.为了这个精确的目的,使用包含帮助器方法的JsonConvert类:

// To convert an XML node contained in string xml into a JSON string   
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);

// To convert JSON text contained in string json into an XML node
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);
Run Code Online (Sandbox Code Playgroud)

这里的文档:使用Json.NET在JSON和XML之间进行转换

  • @StaxMan:我想每个人都同意没有标准化的方式来表示JSON格式的XML文档.你的回答可能被低估了,因为它实际上没有回答这个问题.OP并没有问他是否*应该进行转换,而是他是否可以*使用已经可以使用的工具来做. (7认同)
  • 我找不到这堂课.我使用NewtonSoft Json.net 3.5. (3认同)
  • 看来此功能已移至JSON.NET 3.5中的Newtonsoft.Json.Converters.XmlNodeConverter类:http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Converters_XmlNodeConverter.htm (3认同)
  • 惊喜 - 这是XML和JSON之间的阻抗,以及为什么(IMO)在两者之间_directly_转换不是一个好主意的原因.但是,嘿,有很多开发人员在这里强烈反对(根据我的回答),并不介意这些意外的数据转换或潜在的数据丢失...... (3认同)
  • 仅供参考,这里有潜在的问题。当我将xml节点数组转换为json时,它正在json中创建数组。但是,当我遍历一个计数为1的xml节点数组时,则json转换不再格式化数组了。具有单个元素的xml数组在此处的翻译中丢失了。 (2认同)

DaF*_*Fi4 43

是的,你可以做到(我这样做)但是在转换时要注意一些悖论,并妥善处理.您不能自动符合所有接口的可能性,并且控制转换的内置支持有限 - 许多JSON结构和值不能自动双向转换.请记住,我使用Newtonsoft JSON库和MS XML库的默认设置,因此您的里程可能会有所不同:

XML - > JSON

  1. 所有数据都变成了字符串数据(例如,你总是得到"假"而不是假,或者"0"不是0)显然,JavaScript在某些情况下对待这些不同.
  2. 如果只有一个或多个XML子元素,则子元素可以成为嵌套对象{}或嵌套数组[ {} {} ...].您将在JavaScript等中使用这两种不同的方式.符合相同模式的XML的不同示例可以通过这种方式生成实际上不同的JSON结构.您可以将属性json:Array ='true'添加到元素中,以便在某些(但不一定是所有)情况下解决此问题.
  3. 你的XML必须格式合理,我注意到它不需要完全符合W3C标准,但是1.你必须有一个根元素和2.你不能用数字开始元素名称是两个强制执行的XML标准我在使用Newtonsoft和MS库时发现了.
  4. 在旧版本中,Blank元素不会转换为JSON.他们被忽略了.空白元素不会变为"元素":null

一个新的更新改变了这一点(感谢Jon Story指出):https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm

JSON - > XML

  1. 您需要一个将转换为根XML元素的顶级对象,否则解析器将失败.
  2. 您的对象名称不能以数字开头,因为它们无法转换为元素(XML在技术上甚至比这更严格)但我可以"逃避"打破其他一些元素命名规则.

请随意提及您注意到的任何其他问题,我已经开发了自己的自定义例程来准备和清理字符串,因为我来回转换.您的情况可能会或可能不会要求准备/清理.正如StaxMan所提到的,你的情况实际上可能需要你在对象之间进行转换......这可能需要适当的接口和一堆case语句/ etc来处理我上面提到的警告.

  • 这!很好地阐述了我简短的(在某些时候被严重否决的)答案的基础——如果你进行盲目的直接转换,会有很多很多的陷阱。它们可能不会阻止特定用途的问题,但对其他人来说也可能非常令人讨厌。 (2认同)
  • 关于 XML -> JSON 上的#4:您可以使用 NullValueHandling 属性来指定应显式包含 null 值 - https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm (2认同)

Ter*_*nja 32

您也可以使用.NET Framework进行这些转换:

JSON to XML:使用System.Runtime.Serialization.Json

var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
    Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));
Run Code Online (Sandbox Code Playgroud)

XML到JSON:使用System.Web.Script.Serialization

var json = new JavaScriptSerializer().Serialize(GetXmlData(XElement.Parse(xmlString)));

private static Dictionary<string, object> GetXmlData(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 => GetXmlData(e)));
    else if (!xml.IsEmpty) attr.Add("_value", xml.Value);

    return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
}
Run Code Online (Sandbox Code Playgroud)

  • @ TimSmith-Aardwolf,[这里](http://pastebin.com/yRpC5Rde)是你需要的所有代码.对于**使用System.Web.Script.Serialization**需要在References中添加**System.Web.Extensions**程序集. (4认同)

Sta*_*Man 29

我不确定这种转换是否有意义(是的,许多人这样做,但主要是通过圆孔强制方形钉) - 结构阻抗不匹配,转换是有损的.所以我建议反对这种格式到格式的转换.

但是如果你这样做,首先从json转换为object,然后从object转换为xml(反之亦然,反向).进行直接转换会导致输出难看,信息丢失或两者兼而有之.


Dav*_*.ca 27

感谢David Brown的回答.在我的JSON.Net 3.5的情况下,转换方法在JsonConvert静态类下:

XmlNode myXmlNode = JsonConvert.DeserializeXmlNode(myJsonString); // is node not note
// or .DeserilizeXmlNode(myJsonString, "root"); // if myJsonString does not have a root
string jsonString = JsonConvert.SerializeXmlNode(myXmlNode);
Run Code Online (Sandbox Code Playgroud)

  • 如果您的数据是一个数组,那么您需要执行以下操作:JsonConvert.DeserializeXmlNode("{\"Row \":"+ json +"}","root").ToXmlString()否则您将获得"XmlNodeConverter"只能转换以对象开头的JSON." 例外. (4认同)

you*_*pal 8

为了不使用外部组件/项目,我搜索了很长时间以找到已接受解决方案的替代代码.由于DynamicJson项目的源代码,我想出了以下内容:

public XmlDocument JsonToXML(string json)
{
    XmlDocument doc = new XmlDocument();

    using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), XmlDictionaryReaderQuotas.Max))
    {
        XElement xml = XElement.Load(reader);
        doc.LoadXml(xml.ToString());
    }

    return doc;
}
Run Code Online (Sandbox Code Playgroud)

注意:我想要一个XmlDocument而不是XElement用于xPath目的.此外,这段代码显然只是从JSON到XML,有各种方法可以做相反的事情.

  • 我最近需要在 SQLCLR 中执行此操作,但无法获取依赖项,因此我硬着头皮编写了这个 [json-to-xml 转换例程](https://gist.github.com/gfody/d7d450dc54a15e586d5b6ab9794073a4),它非常简单,只有大约 20 行代码。 (2认同)

Nim*_*tri 6

以下是将xml转换为json的完整c#代码

public static class JSon
{
public static string XmlToJSON(string xml)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);

    return XmlToJSON(doc);
}
public static string XmlToJSON(XmlDocument xmlDoc)
{
    StringBuilder sbJSON = new StringBuilder();
    sbJSON.Append("{ ");
    XmlToJSONnode(sbJSON, xmlDoc.DocumentElement, true);
    sbJSON.Append("}");
    return sbJSON.ToString();
}

//  XmlToJSONnode:  Output an XmlElement, possibly as part of a higher array
private static void XmlToJSONnode(StringBuilder sbJSON, XmlElement node, bool showNodeName)
{
    if (showNodeName)
        sbJSON.Append("\"" + SafeJSON(node.Name) + "\": ");
    sbJSON.Append("{");
    // Build a sorted list of key-value pairs
    //  where   key is case-sensitive nodeName
    //          value is an ArrayList of string or XmlElement
    //  so that we know whether the nodeName is an array or not.
    SortedList<string, object> childNodeNames = new SortedList<string, object>();

    //  Add in all node attributes
    if (node.Attributes != null)
        foreach (XmlAttribute attr in node.Attributes)
            StoreChildNode(childNodeNames, attr.Name, attr.InnerText);

    //  Add in all nodes
    foreach (XmlNode cnode in node.ChildNodes)
    {
        if (cnode is XmlText)
            StoreChildNode(childNodeNames, "value", cnode.InnerText);
        else if (cnode is XmlElement)
            StoreChildNode(childNodeNames, cnode.Name, cnode);
    }

    // Now output all stored info
    foreach (string childname in childNodeNames.Keys)
    {
        List<object> alChild = (List<object>)childNodeNames[childname];
        if (alChild.Count == 1)
            OutputNode(childname, alChild[0], sbJSON, true);
        else
        {
            sbJSON.Append(" \"" + SafeJSON(childname) + "\": [ ");
            foreach (object Child in alChild)
                OutputNode(childname, Child, sbJSON, false);
            sbJSON.Remove(sbJSON.Length - 2, 2);
            sbJSON.Append(" ], ");
        }
    }
    sbJSON.Remove(sbJSON.Length - 2, 2);
    sbJSON.Append(" }");
}

//  StoreChildNode: Store data associated with each nodeName
//                  so that we know whether the nodeName is an array or not.
private static void StoreChildNode(SortedList<string, object> childNodeNames, string nodeName, object nodeValue)
{
    // Pre-process contraction of XmlElement-s
    if (nodeValue is XmlElement)
    {
        // Convert  <aa></aa> into "aa":null
        //          <aa>xx</aa> into "aa":"xx"
        XmlNode cnode = (XmlNode)nodeValue;
        if (cnode.Attributes.Count == 0)
        {
            XmlNodeList children = cnode.ChildNodes;
            if (children.Count == 0)
                nodeValue = null;
            else if (children.Count == 1 && (children[0] is XmlText))
                nodeValue = ((XmlText)(children[0])).InnerText;
        }
    }
    // Add nodeValue to ArrayList associated with each nodeName
    // If nodeName doesn't exist then add it
    List<object> ValuesAL;

    if (childNodeNames.ContainsKey(nodeName))
    {
        ValuesAL = (List<object>)childNodeNames[nodeName];
    }
    else
    {
        ValuesAL = new List<object>();
        childNodeNames[nodeName] = ValuesAL;
    }
    ValuesAL.Add(nodeValue);
}

private static void OutputNode(string childname, object alChild, StringBuilder sbJSON, bool showNodeName)
{
    if (alChild == null)
    {
        if (showNodeName)
            sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
        sbJSON.Append("null");
    }
    else if (alChild is string)
    {
        if (showNodeName)
            sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
        string sChild = (string)alChild;
        sChild = sChild.Trim();
        sbJSON.Append("\"" + SafeJSON(sChild) + "\"");
    }
    else
        XmlToJSONnode(sbJSON, (XmlElement)alChild, showNodeName);
    sbJSON.Append(", ");
}

// Make a string safe for JSON
private static string SafeJSON(string sIn)
{
    StringBuilder sbOut = new StringBuilder(sIn.Length);
    foreach (char ch in sIn)
    {
        if (Char.IsControl(ch) || ch == '\'')
        {
            int ich = (int)ch;
            sbOut.Append(@"\u" + ich.ToString("x4"));
            continue;
        }
        else if (ch == '\"' || ch == '\\' || ch == '/')
        {
            sbOut.Append('\\');
        }
        sbOut.Append(ch);
    }
    return sbOut.ToString();
 }
}
Run Code Online (Sandbox Code Playgroud)

要将给定的XML字符串转换为JSON,只需调用XmlToJSON()函数,如下所示.

string xml = "<menu id=\"file\" value=\"File\"> " +
              "<popup>" +
                "<menuitem value=\"New\" onclick=\"CreateNewDoc()\" />" +
                "<menuitem value=\"Open\" onclick=\"OpenDoc()\" />" +
                "<menuitem value=\"Close\" onclick=\"CloseDoc()\" />" +
              "</popup>" +
            "</menu>";

string json = JSON.XmlToJSON(xml);
// json = { "menu": {"id": "file", "popup": { "menuitem": [ {"onclick": "CreateNewDoc()", "value": "New" }, {"onclick": "OpenDoc()", "value": "Open" }, {"onclick": "CloseDoc()", "value": "Close" } ] }, "value": "File" }}
Run Code Online (Sandbox Code Playgroud)