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

时间:2022-04-24 21:49:50

I started to use Json.NET to convert a string in JSON format to object or viceversa. I am not sure in the Json.NET framework, is it possible to convert a string in JSON to XML format and viceversa?

我开始使用Json。将JSON格式的字符串转换为object或viceversa。在Json中我不确定。NET framework,是否可以将JSON中的字符串转换为XML格式和viceversa?

11 个解决方案

#1


351  

Yes. Using the JsonConvert class which contains helper methods for this precise purpose:

是的。使用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);

Documentation here: Converting between JSON and XML with Json.NET

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

#2


35  

Yes, you can do it (I do) but Be aware of some paradoxes when converting, and handle appropriately. You cannot automatically conform to all interface possibilities, and there is limited built-in support in controlling the conversion- many JSON structures and values cannot automatically be converted both ways. Keep in mind I am using the default settings with Newtonsoft JSON library and MS XML library, so your mileage may vary:

是的,您可以这样做(我可以),但是在转换时要注意一些悖论,并适当地处理。您不能自动地遵从所有的接口可能性,并且在控制转换方面有有限的内置支持—许多JSON结构和值不能自动地以两种方式转换。请记住,我使用的是Newtonsoft JSON库和MS XML库的默认设置,因此您的里程可能有所不同:

XML -> JSON

  1. All data becomes string data (for example you will always get "false" not false or "0" not 0) Obviously JavaScript treats these differently in certain cases.
  2. 所有数据都变成了字符串数据(例如,您总是会得到“false”而不是“0”而不是0)显然,JavaScript在某些情况下会有不同的处理方式。
  3. Children elements can become nested-object {} OR nested-array [ {} {} ...] depending if there is only one or more than one XML child-element. You would consume these two differently in JavaScript, etc. Different examples of XML conforming to the same schema can produce actually different JSON structures this way. You can add the attribute json:Array='true' to your element to workaround this in some (but not necessarily all) cases.
  4. 子元素可以变成nested-object{}或nested-array[{}]…]取决于是否只有一个或多个XML子元素。您将在JavaScript中以不同的方式使用这两种方式。不同的XML符合同一模式的示例可以通过这种方式产生不同的JSON结构。您可以将属性json:Array='true'添加到元素中,以便在某些(但不一定是所有)情况下解决这个问题。
  5. Your XML must be fairly well-formed, I have noticed it doesn't need to perfectly conform to W3C standard, but 1. you must have a root element and 2. you cannot start element names with numbers are two of the enforced XML standards I have found when using Newtonsoft and MS libraries.
  6. 您的XML必须是格式良好的,我注意到它不需要完全符合W3C标准,而是1。必须有根元素和2。在使用Newtonsoft和MS库时,我发现,不能使用数字启动元素名称。
  7. Blank elements do not convert to JSON. They are ignored. A blank element does not become "element":null
  8. 空白元素不转换为JSON。他们将被忽略。空白元素不会变成“元素”:null。

JSON -> XML

  1. You need a top level object that will convert to a root XML element or the parser will fail.
  2. 您需要一个*对象,该对象将转换为根XML元素,否则解析器将失败。
  3. Your object names cannot start with a number, as they cannot be converted to elements (XML is technically even more strict than this) but I can 'get away' with breaking some of the other element naming rules.
  4. 您的对象名称不能从一个数字开始,因为它们不能转换为元素(XML在技术上甚至比这更严格),但是我可以通过破坏其他元素的命名规则来“摆脱”。

Please feel free to mention any other issues you have noticed, I have developed my own custom routines for preparing and cleaning the strings as I convert back and forth. Your situation may or may not call for prep/cleanup. As StaxMan mentions, your situation may actually require that you convert between objects...this could entail appropriate interfaces and a bunch of case statements/etc to handle the caveats I mention above.

请随意提及您注意到的任何其他问题,我开发了我自己的自定义例程来准备和清理字符串,因为我来回转换。你的情况可能需要也可能不需要准备/清理。正如StaxMan提到的,您的情况可能实际上要求您在对象之间进行转换……这可能需要适当的接口和大量的case语句等来处理我上面提到的注意事项。

#3


26  

Thanks for David Brown's answer. In my case of JSON.Net 3.5, the convert methods are under the JsonConvert static class:

谢谢大卫·布朗的回答。在我的例子中是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);

#4


23  

You can do these conversions also with the .NET Framework:

你也可以通过。net框架进行这些转换:

JSON to XML: by using System.Runtime.Serialization.Json

JSON到XML:通过使用system . runtime . serializ.json

var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
    Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));

XML to JSON: by using System.Web.Script.Serialization

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

#5


20  

I'm not sure there is point in such conversion (yes, many do it, but mostly to force a square peg through round hole) -- there is structural impedance mismatch, and conversion is lossy. So I would recommend against such format-to-format transformations.

我不确定这种转换是否有意义(是的,很多人这样做,但主要是为了迫使方柱穿过圆孔)——存在结构阻抗失配,转换是有损的。因此,我建议反对这种格式到格式的转换。

But if you do it, first convert from json to object, then from object to xml (and vice versa for reverse direction). Doing direct transformation leads to ugly output, loss of information, or possibly both.

但如果您这样做,首先将json转换为object,然后将对象转换为xml(反之亦然)。直接转换会导致难看的输出、信息的丢失,或者两者兼而有之。

#6


8  

I searched for a long time to find alternative code to the accepted solution in the hopes of not using an external assembly/project. I came up with the following thanks to the source code of the DynamicJson project:

为了不使用外部程序集/项目,我搜索了很长一段时间来寻找可接受的解决方案的替代代码。感谢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;
}

Note: I wanted an XmlDocument rather than an XElement for xPath purposes. Also, this code obviously only goes from JSON to XML, there are various ways to do the opposite.

注意:出于xPath目的,我希望使用XmlDocument而不是XElement。而且,这段代码显然只从JSON到XML,有很多方法可以做相反的事情。

#7


4  

Here is the full c# code to convert xml to json

下面是将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();
 }
}

To convert a given XML string to JSON, simply call XmlToJSON() function as below.

要将给定的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" }}

#8


4  

Try this function. I just wrote it and haven't had much of a chance to test it, but my preliminary tests are promising.

试试这个功能。我只是写了它,还没有太多机会去测试它,但是我的初步测试是有希望的。

public static XmlDocument JsonToXml(string json)
{
    XmlNode newNode = null;
    XmlNode appendToNode = null;
    XmlDocument returnXmlDoc = new XmlDocument();
    returnXmlDoc.LoadXml("<Document />");
    XmlNode rootNode = returnXmlDoc.SelectSingleNode("Document");
    appendToNode = rootNode;

    string[] arrElementData;
    string[] arrElements = json.Split('\r');
    foreach (string element in arrElements)
    {
        string processElement = element.Replace("\r", "").Replace("\n", "").Replace("\t", "").Trim();
        if ((processElement.IndexOf("}") > -1 || processElement.IndexOf("]") > -1) && appendToNode != rootNode)
        {
            appendToNode = appendToNode.ParentNode;
        }
        else if (processElement.IndexOf("[") > -1)
        {
            processElement = processElement.Replace(":", "").Replace("[", "").Replace("\"", "").Trim();
            newNode = returnXmlDoc.CreateElement(processElement);
            appendToNode.AppendChild(newNode);
            appendToNode = newNode;
        }
        else if (processElement.IndexOf("{") > -1 && processElement.IndexOf(":") > -1)
        {
            processElement = processElement.Replace(":", "").Replace("{", "").Replace("\"", "").Trim();
            newNode = returnXmlDoc.CreateElement(processElement);
            appendToNode.AppendChild(newNode);
            appendToNode = newNode;
        }
        else
        {
            if (processElement.IndexOf(":") > -1)
            {
                arrElementData = processElement.Replace(": \"", ":").Replace("\",", "").Replace("\"", "").Split(':');
                newNode = returnXmlDoc.CreateElement(arrElementData[0]);
                for (int i = 1; i < arrElementData.Length; i++)
                {
                    newNode.InnerText += arrElementData[i];
                }

                appendToNode.AppendChild(newNode);
            }
        }
    }

    return returnXmlDoc;
}

#9


2  

Here is a simple snippet that converts a XmlNode (recursively) into a hashtable, and groups multiple instances of the same child into an array (as an ArrayList). The Hashtable is usually accepted to convert into JSON by most of the JSON libraries.

下面是一个简单的代码片段,它将XmlNode(递归地)转换为hashtable,并将同一子实例的多个实例分组为数组(作为ArrayList)。大多数JSON库通常接受Hashtable来转换为JSON。

protected object convert(XmlNode root){
    Hashtable obj = new Hashtable();
    for(int i=0,n=root.ChildNodes.Count;i<n;i++){
        object result = null;
        XmlNode current = root.ChildNodes.Item(i);

        if(current.NodeType != XmlNodeType.Text)
            result = convert(current);
        else{
            int resultInt;
            double resultFloat;
            bool resultBoolean;
            if(Int32.TryParse(current.Value, out resultInt)) return resultInt;
            if(Double.TryParse(current.Value, out resultFloat)) return resultFloat;
            if(Boolean.TryParse(current.Value, out resultBoolean)) return resultBoolean;
            return current.Value;
        }

        if(obj[current.Name] == null)
            obj[current.Name] = result;
        else if(obj[current.Name].GetType().Equals(typeof(ArrayList)))
            ((ArrayList)obj[current.Name]).Add(result);
        else{
            ArrayList collision = new ArrayList();
            collision.Add(obj[current.Name]);
            collision.Add(result);
            obj[current.Name] = collision;
        }
    }

    return obj;
}

#10


0  

I did like David Brown said but I got the following exception.

我确实像大卫·布朗说的那样,但我有以下的例外。

$exception {"There are multiple root elements. Line , position ."} System.Xml.XmlException

One solution would be to modify the XML file with a root element but that is not always necessary and for an XML stream it might not be possible either. My solution below:

一种解决方案是使用根元素修改XML文件,但这并不总是必需的,而且对于XML流来说也不可能。我的解决方案如下:

var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\..\App_Data"));
var directoryInfo = new DirectoryInfo(path);
var fileInfos = directoryInfo.GetFiles("*.xml");

foreach (var fileInfo in fileInfos)
{
    XmlDocument doc = new XmlDocument();
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Fragment;

    using (XmlReader reader = XmlReader.Create(fileInfo.FullName, settings))
    {
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
            {
                var node = doc.ReadNode(reader);
                string json = JsonConvert.SerializeXmlNode(node);
            }
        }
    }
}

Example XML that generates the error:

生成错误的示例XML:

<parent>
    <child>
        Text
    </child>
</parent>
<parent>
    <child>
        <grandchild>
            Text
        </grandchild>
        <grandchild>
            Text
        </grandchild>
    </child>
    <child>
        Text
    </child>
</parent>

#11


0  

Cinchoo ETL - an open source library available to do the conversion of Xml to JSON easily with few lines of code

Cinchoo ETL——一个开放源码库,可以用几行代码轻松地将Xml转换为JSON

Xml -> JSON:

Xml - > JSON:

using (var p = new ChoXmlReader("sample.xml"))
{
    using (var w = new ChoJSONWriter("sample.json"))
    {
        w.Write(p);
    }
}

JSON -> Xml:

JSON - > Xml:

using (var p = new ChoJsonReader("sample.json"))
{
    using (var w = new ChoXmlWriter("sample.xml"))
    {
        w.Write(p);
    }
}

Checkout CodeProject article for some additional help.

签出代码项目文章以获得一些额外的帮助。

Disclaimer: I'm the author of this library.

免责声明:我是这个图书馆的作者。

#1


351  

Yes. Using the JsonConvert class which contains helper methods for this precise purpose:

是的。使用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);

Documentation here: Converting between JSON and XML with Json.NET

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

#2


35  

Yes, you can do it (I do) but Be aware of some paradoxes when converting, and handle appropriately. You cannot automatically conform to all interface possibilities, and there is limited built-in support in controlling the conversion- many JSON structures and values cannot automatically be converted both ways. Keep in mind I am using the default settings with Newtonsoft JSON library and MS XML library, so your mileage may vary:

是的,您可以这样做(我可以),但是在转换时要注意一些悖论,并适当地处理。您不能自动地遵从所有的接口可能性,并且在控制转换方面有有限的内置支持—许多JSON结构和值不能自动地以两种方式转换。请记住,我使用的是Newtonsoft JSON库和MS XML库的默认设置,因此您的里程可能有所不同:

XML -> JSON

  1. All data becomes string data (for example you will always get "false" not false or "0" not 0) Obviously JavaScript treats these differently in certain cases.
  2. 所有数据都变成了字符串数据(例如,您总是会得到“false”而不是“0”而不是0)显然,JavaScript在某些情况下会有不同的处理方式。
  3. Children elements can become nested-object {} OR nested-array [ {} {} ...] depending if there is only one or more than one XML child-element. You would consume these two differently in JavaScript, etc. Different examples of XML conforming to the same schema can produce actually different JSON structures this way. You can add the attribute json:Array='true' to your element to workaround this in some (but not necessarily all) cases.
  4. 子元素可以变成nested-object{}或nested-array[{}]…]取决于是否只有一个或多个XML子元素。您将在JavaScript中以不同的方式使用这两种方式。不同的XML符合同一模式的示例可以通过这种方式产生不同的JSON结构。您可以将属性json:Array='true'添加到元素中,以便在某些(但不一定是所有)情况下解决这个问题。
  5. Your XML must be fairly well-formed, I have noticed it doesn't need to perfectly conform to W3C standard, but 1. you must have a root element and 2. you cannot start element names with numbers are two of the enforced XML standards I have found when using Newtonsoft and MS libraries.
  6. 您的XML必须是格式良好的,我注意到它不需要完全符合W3C标准,而是1。必须有根元素和2。在使用Newtonsoft和MS库时,我发现,不能使用数字启动元素名称。
  7. Blank elements do not convert to JSON. They are ignored. A blank element does not become "element":null
  8. 空白元素不转换为JSON。他们将被忽略。空白元素不会变成“元素”:null。

JSON -> XML

  1. You need a top level object that will convert to a root XML element or the parser will fail.
  2. 您需要一个*对象,该对象将转换为根XML元素,否则解析器将失败。
  3. Your object names cannot start with a number, as they cannot be converted to elements (XML is technically even more strict than this) but I can 'get away' with breaking some of the other element naming rules.
  4. 您的对象名称不能从一个数字开始,因为它们不能转换为元素(XML在技术上甚至比这更严格),但是我可以通过破坏其他元素的命名规则来“摆脱”。

Please feel free to mention any other issues you have noticed, I have developed my own custom routines for preparing and cleaning the strings as I convert back and forth. Your situation may or may not call for prep/cleanup. As StaxMan mentions, your situation may actually require that you convert between objects...this could entail appropriate interfaces and a bunch of case statements/etc to handle the caveats I mention above.

请随意提及您注意到的任何其他问题,我开发了我自己的自定义例程来准备和清理字符串,因为我来回转换。你的情况可能需要也可能不需要准备/清理。正如StaxMan提到的,您的情况可能实际上要求您在对象之间进行转换……这可能需要适当的接口和大量的case语句等来处理我上面提到的注意事项。

#3


26  

Thanks for David Brown's answer. In my case of JSON.Net 3.5, the convert methods are under the JsonConvert static class:

谢谢大卫·布朗的回答。在我的例子中是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);

#4


23  

You can do these conversions also with the .NET Framework:

你也可以通过。net框架进行这些转换:

JSON to XML: by using System.Runtime.Serialization.Json

JSON到XML:通过使用system . runtime . serializ.json

var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
    Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));

XML to JSON: by using System.Web.Script.Serialization

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

#5


20  

I'm not sure there is point in such conversion (yes, many do it, but mostly to force a square peg through round hole) -- there is structural impedance mismatch, and conversion is lossy. So I would recommend against such format-to-format transformations.

我不确定这种转换是否有意义(是的,很多人这样做,但主要是为了迫使方柱穿过圆孔)——存在结构阻抗失配,转换是有损的。因此,我建议反对这种格式到格式的转换。

But if you do it, first convert from json to object, then from object to xml (and vice versa for reverse direction). Doing direct transformation leads to ugly output, loss of information, or possibly both.

但如果您这样做,首先将json转换为object,然后将对象转换为xml(反之亦然)。直接转换会导致难看的输出、信息的丢失,或者两者兼而有之。

#6


8  

I searched for a long time to find alternative code to the accepted solution in the hopes of not using an external assembly/project. I came up with the following thanks to the source code of the DynamicJson project:

为了不使用外部程序集/项目,我搜索了很长一段时间来寻找可接受的解决方案的替代代码。感谢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;
}

Note: I wanted an XmlDocument rather than an XElement for xPath purposes. Also, this code obviously only goes from JSON to XML, there are various ways to do the opposite.

注意:出于xPath目的,我希望使用XmlDocument而不是XElement。而且,这段代码显然只从JSON到XML,有很多方法可以做相反的事情。

#7


4  

Here is the full c# code to convert xml to json

下面是将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();
 }
}

To convert a given XML string to JSON, simply call XmlToJSON() function as below.

要将给定的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" }}

#8


4  

Try this function. I just wrote it and haven't had much of a chance to test it, but my preliminary tests are promising.

试试这个功能。我只是写了它,还没有太多机会去测试它,但是我的初步测试是有希望的。

public static XmlDocument JsonToXml(string json)
{
    XmlNode newNode = null;
    XmlNode appendToNode = null;
    XmlDocument returnXmlDoc = new XmlDocument();
    returnXmlDoc.LoadXml("<Document />");
    XmlNode rootNode = returnXmlDoc.SelectSingleNode("Document");
    appendToNode = rootNode;

    string[] arrElementData;
    string[] arrElements = json.Split('\r');
    foreach (string element in arrElements)
    {
        string processElement = element.Replace("\r", "").Replace("\n", "").Replace("\t", "").Trim();
        if ((processElement.IndexOf("}") > -1 || processElement.IndexOf("]") > -1) && appendToNode != rootNode)
        {
            appendToNode = appendToNode.ParentNode;
        }
        else if (processElement.IndexOf("[") > -1)
        {
            processElement = processElement.Replace(":", "").Replace("[", "").Replace("\"", "").Trim();
            newNode = returnXmlDoc.CreateElement(processElement);
            appendToNode.AppendChild(newNode);
            appendToNode = newNode;
        }
        else if (processElement.IndexOf("{") > -1 && processElement.IndexOf(":") > -1)
        {
            processElement = processElement.Replace(":", "").Replace("{", "").Replace("\"", "").Trim();
            newNode = returnXmlDoc.CreateElement(processElement);
            appendToNode.AppendChild(newNode);
            appendToNode = newNode;
        }
        else
        {
            if (processElement.IndexOf(":") > -1)
            {
                arrElementData = processElement.Replace(": \"", ":").Replace("\",", "").Replace("\"", "").Split(':');
                newNode = returnXmlDoc.CreateElement(arrElementData[0]);
                for (int i = 1; i < arrElementData.Length; i++)
                {
                    newNode.InnerText += arrElementData[i];
                }

                appendToNode.AppendChild(newNode);
            }
        }
    }

    return returnXmlDoc;
}

#9


2  

Here is a simple snippet that converts a XmlNode (recursively) into a hashtable, and groups multiple instances of the same child into an array (as an ArrayList). The Hashtable is usually accepted to convert into JSON by most of the JSON libraries.

下面是一个简单的代码片段,它将XmlNode(递归地)转换为hashtable,并将同一子实例的多个实例分组为数组(作为ArrayList)。大多数JSON库通常接受Hashtable来转换为JSON。

protected object convert(XmlNode root){
    Hashtable obj = new Hashtable();
    for(int i=0,n=root.ChildNodes.Count;i<n;i++){
        object result = null;
        XmlNode current = root.ChildNodes.Item(i);

        if(current.NodeType != XmlNodeType.Text)
            result = convert(current);
        else{
            int resultInt;
            double resultFloat;
            bool resultBoolean;
            if(Int32.TryParse(current.Value, out resultInt)) return resultInt;
            if(Double.TryParse(current.Value, out resultFloat)) return resultFloat;
            if(Boolean.TryParse(current.Value, out resultBoolean)) return resultBoolean;
            return current.Value;
        }

        if(obj[current.Name] == null)
            obj[current.Name] = result;
        else if(obj[current.Name].GetType().Equals(typeof(ArrayList)))
            ((ArrayList)obj[current.Name]).Add(result);
        else{
            ArrayList collision = new ArrayList();
            collision.Add(obj[current.Name]);
            collision.Add(result);
            obj[current.Name] = collision;
        }
    }

    return obj;
}

#10


0  

I did like David Brown said but I got the following exception.

我确实像大卫·布朗说的那样,但我有以下的例外。

$exception {"There are multiple root elements. Line , position ."} System.Xml.XmlException

One solution would be to modify the XML file with a root element but that is not always necessary and for an XML stream it might not be possible either. My solution below:

一种解决方案是使用根元素修改XML文件,但这并不总是必需的,而且对于XML流来说也不可能。我的解决方案如下:

var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\..\App_Data"));
var directoryInfo = new DirectoryInfo(path);
var fileInfos = directoryInfo.GetFiles("*.xml");

foreach (var fileInfo in fileInfos)
{
    XmlDocument doc = new XmlDocument();
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Fragment;

    using (XmlReader reader = XmlReader.Create(fileInfo.FullName, settings))
    {
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
            {
                var node = doc.ReadNode(reader);
                string json = JsonConvert.SerializeXmlNode(node);
            }
        }
    }
}

Example XML that generates the error:

生成错误的示例XML:

<parent>
    <child>
        Text
    </child>
</parent>
<parent>
    <child>
        <grandchild>
            Text
        </grandchild>
        <grandchild>
            Text
        </grandchild>
    </child>
    <child>
        Text
    </child>
</parent>

#11


0  

Cinchoo ETL - an open source library available to do the conversion of Xml to JSON easily with few lines of code

Cinchoo ETL——一个开放源码库,可以用几行代码轻松地将Xml转换为JSON

Xml -> JSON:

Xml - > JSON:

using (var p = new ChoXmlReader("sample.xml"))
{
    using (var w = new ChoJSONWriter("sample.json"))
    {
        w.Write(p);
    }
}

JSON -> Xml:

JSON - > Xml:

using (var p = new ChoJsonReader("sample.json"))
{
    using (var w = new ChoXmlWriter("sample.xml"))
    {
        w.Write(p);
    }
}

Checkout CodeProject article for some additional help.

签出代码项目文章以获得一些额外的帮助。

Disclaimer: I'm the author of this library.

免责声明:我是这个图书馆的作者。