Comment convertir JSON en XML ou XML en JSON?

j'ai commencé à utiliser Json.NET pour convertir une chaîne de caractères au format JSON en objet ou viceversa. I am not sure in the Json.NET cadre, est-il possible de convertir une chaîne de caractères dans JSON en format XML et viceversa?

240
demandé sur Termininja 2009-05-02 06:25:41

12 réponses

Oui. En utilisant la classe JsonConvert qui contient des méthodes d'aide pour ce but précis:

// 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 ici: conversion entre JSON et XML avec Json.NET

370
répondu David Brown 2014-02-05 10:27:37

Oui, vous peut de le faire (je le fais), mais Être conscient de certains paradoxes lors de la conversion, et de gérer de manière appropriée. Vous ne pouvez pas vous conformer automatiquement à toutes les possibilités d'interface, et il y a peu de support intégré dans le contrôle de la conversion-de nombreuses structures et valeurs de JSON ne peuvent pas être converties automatiquement dans les deux sens. Gardez à l'esprit que j'utilise les paramètres par défaut avec Newtonsoft JSON library et MS XML library, de sorte que votre kilométrage peut varier:

XML - > JSON

  1. toutes les données deviennent des données de chaîne (par exemple, vous obtiendrez toujours "false" pas "false ou " 0 " pas 0 ) évidemment JavaScript traite ces données différemment dans certains cas.
  2. les éléments enfants peuvent devenir imbriqués-objet {} ou imbriqués-tableau [ {} {} ...] selon S'il N'y a qu'un ou plusieurs XML enfant-élément. Vous les consommeriez différemment en JavaScript,etc. Différents exemples de XML conformes au même schéma peuvent produire en fait différentes structures JSON de cette façon. Vous pouvez ajouter l'attribut json:Array='true' à votre élément pour contourner ce problème dans certains cas (mais pas nécessairement tous).
  3. votre XML doit être assez bien formé, j'ai remarqué qu'il n'a pas besoin de parfaitement conforme à la norme W3C, mais 1. vous devez avoir un élément racine et 2. vous ne pouvez pas démarrer les noms d'éléments avec des numéros sont deux des normes XML appliquées que j'ai trouvées en utilisant les bibliothèques Newtonsoft et MS.
  4. Les éléments Vierges
  5. ne se convertissent pas en JSON. Ils sont ignorés. Un élément vide ne devient pas "element": null

JSON - > XML

  1. vous avez besoin d'un objet de haut niveau qui sera convertissez en un élément racine XML ou l'analyseur échouera.
  2. vos noms d'objets ne peuvent pas commencer par un nombre, car ils ne peuvent pas être convertis en éléments (XML est techniquement encore plus strict que cela) mais je peux 'm'en tirer' en brisant certaines des autres règles de nommage d'éléments.

, n'hésitez pas à mentionner toutes les autres questions que vous avez remarqué, j'ai développé mes propres routines personnalisées pour la préparation et le nettoyage des cordes comme je le convertir en arrière et de suite. Votre situation peut exiger ou non une préparation ou un nettoyage. Comme StaxMan le mentionne, votre situation peut exiger que vous convertissiez entre les objets...cela pourrait nécessiter des interfaces appropriées et un tas d'énoncés de cas/etc pour gérer les mises en garde que je mentionne ci-dessus.

35
répondu montewhizdoh 2018-04-20 19:34:20

vous pouvez faire ces conversions aussi avec le .net Framework:

JSON XML: à l'aide de du Système.Runtime.Sérialisation.Json

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

XML en JSON: à l'aide de du Système.Web.Script.La sérialisation

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 } };
}
26
répondu Termininja 2016-05-22 05:20:49

Merci pour la réponse de David Brown. Dans mon cas de JSON.Net 3.5, les méthodes de conversion sont sous la classe statique 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);
26
répondu David.Chu.ca 2016-08-10 17:09:51

Je ne suis pas sûr qu'il y ait un point dans une telle conversion (oui, beaucoup le font, mais surtout pour forcer une cheville carrée à travers un trou rond) -- il y a une inadéquation structurelle d'impédance, et la conversion est perdue. Je recommande donc de ne pas procéder à de telles transformations de format à format.

mais si vous le faites, convertissez d'abord de json en objet, puis de object en xml (et vice versa pour sens inverse). Faire une transformation directe mène à des résultats laids, perte d'information, ou peut-être les deux.

22
répondu StaxMan 2012-05-16 19:34:55

j'ai cherché longtemps à trouver un code alternatif à la solution acceptée dans l'espoir de ne pas utiliser une assemblée/projet externe. Je suis venu avec les suivants grâce au code source du DynamicJson projet:

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: je voulais un XmlDocument plutôt qu'un XElement pour les besoins de xPath. En outre, ce code ne va évidemment que de JSON à XML, il y a plusieurs façons de faire le contraire.

8
répondu yourbuddypal 2016-04-04 20:43:08

voici le code c complet pour convertir xml en json

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

pour convertir une chaîne XML donnée en JSON, il suffit d'appeler la fonction XmlToJSON() comme ci-dessous.

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" }}
5
répondu Nimesh khatri 2016-04-11 06:47:59

essayez cette fonction. Je viens d'écrire et n'en ai pas eu beaucoup de chance de le tester, mais mes essais préliminaires sont prometteurs.

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;
}
4
répondu Jamon Crockom 2016-04-21 16:34:46

voici un simple snippet qui convertit un XmlNode (récursivement) en un hashtable, et regroupe plusieurs instances du même enfant en un tableau (comme un Arrayylist). Le Hashtable est généralement accepté pour être converti en JSON par la plupart des bibliothèques 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;
}
2
répondu kronenthaler 2014-06-06 07:50:34

J'ai fait comme David Brown dit, mais j'ai eu l'exception suivante.

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

une solution serait de modifier le fichier XML avec un élément racine mais ce n'est pas toujours nécessaire et pour un flux XML cela pourrait ne pas être possible non plus. Ma solution ci-dessous:

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

exemple XML qui génère l'erreur:

<parent>
    <child>
        Text
    </child>
</parent>
<parent>
    <child>
        <grandchild>
            Text
        </grandchild>
        <grandchild>
            Text
        </grandchild>
    </child>
    <child>
        Text
    </child>
</parent>
0
répondu Ogglas 2017-08-30 09:39:54

Cinchoo ETL - une bibliothèque libre Disponible pour faire la conversion de Xml en JSON facilement avec quelques lignes de code

Xml - > JSON:

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

JSON - > Xml:

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

vérifier L'article Codeprojet pour une aide supplémentaire.

Avertissement: je suis l'auteur de cette bibliothèque.

0
répondu RajN 2018-05-01 14:42:01

j'ai utilisé les méthodes ci-dessous pour convertir le JSON en XML

        List<Item> items;
        public void LoadJsonAndReadToXML()
        {
            using (StreamReader r = new StreamReader(@"E:\Json\overiddenhotelranks.json"))
            {
                string json = r.ReadToEnd();
                items = JsonConvert.DeserializeObject<List<Item>>(json);
                ReadToXML();
            }
        }

et

        public void ReadToXML()
        {    
            try
            {
                var xEle = new XElement("Items",
                            from item in items
                            select new XElement("Item",
                                           new XElement("mhid", item.mhid),
                                           new XElement("hotelName", item.hotelName),
                                           new XElement("destination", item.destination),
                                           new XElement("destinationID", item.destinationID),
                                           new XElement("rank", item.rank),
                                           new XElement("toDisplayOnFod", item.toDisplayOnFod),
                                           new XElement("comment", item.comment),
                                           new XElement("Destinationcode", item.Destinationcode),
                                           new XElement("LoadDate", item.LoadDate)
                                       ));

                xEle.Save("E:\employees.xml");
                Console.WriteLine("Converted to XML");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }

j'ai utilisé la classe article nommé pour représenter les éléments

    public class Item
    {
        public int mhid { get; set; }
        public string hotelName { get; set; }
        public string destination { get; set; }
        public int destinationID { get; set; }
        public int rank { get; set; }
        public int toDisplayOnFod { get; set; }
        public string comment { get; set; }
        public string Destinationcode { get; set; }
        public string LoadDate { get; set; }

    }

ça marche....

0
répondu Sai Ram Sagar 2018-09-05 13:12:27