web-dev-qa-db-fra.com

Comment convertir un fichier JSON en XML ou XML en JSON?

J'ai commencé à utiliser Json.NET pour convertir une chaîne au format JSON en objet ou vice-versa. Je ne suis pas sûr dans le framework Json.NET, est-il possible de convertir une chaîne au format JSON au format XML et vice-versa?

246
David.Chu.ca

Oui. Utilisation de la classe JsonConvert qui contient des méthodes d'assistance dans 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

391
David Brown

Oui, vous pouvez le faites (je le fais), mais soyez conscient de certains paradoxes lors de la conversion et gérez-le de manière appropriée. Vous ne pouvez pas automatiquement vous conformer à toutes les possibilités d'interface et la prise en charge intégrée de la conversion est limitée. De nombreuses structures et valeurs JSON ne peuvent pas être converties automatiquement dans les deux sens. N'oubliez pas que j'utilise les paramètres par défaut avec la bibliothèque Newtonsoft JSON et la bibliothèque MS XML. Votre kilométrage peut donc varier:

XML -> JSON

  1. Toutes les données deviennent des données de chaîne (par exemple, vous obtiendrez toujours "false" et non false ou "0" et 0) Évidemment, JavaScript les traite différemment dans certains cas.
  2. Les éléments enfants peuvent devenir un objet imbriqué {} OR un tableau imbriqué [ {} {} ...] selon qu'il existe un ou plusieurs éléments enfants XML. Vous utiliseriez ces deux manières différemment en JavaScript, etc. Différents exemples de XML conformes au même schéma peuvent ainsi générer des structures JSON différentes. Vous pouvez ajouter l'attribut json: Array = 'true' à votre élément pour contourner ce problème dans certains cas (mais pas nécessairement dans tous).
  3. Votre XML doit être assez bien formé, j'ai remarqué qu'il n'était pas nécessaire qu'il soit parfaitement conforme à la norme W3C, mais 1. vous devez avoir un élément racine et 2. vous ne pouvez pas commencer les noms d'élément avec des nombres sont deux des suivants: les normes XML appliquées que j'ai trouvées lors de l'utilisation des bibliothèques Newtonsoft et MS.
  4. Dans les versions antérieures, les éléments vierges ne sont pas convertis en JSON. Ils sont ignorés. Un élément vide ne devient pas "element": null 

Une nouvelle mise à jour modifie cela (merci à Jon Story de l'avoir signalé): https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm

JSON -> XML

  1. Vous avez besoin d'un objet de niveau supérieur qui convertira en un élément XML racine, sinon l'analyseur échouera.
  2. Vos noms d'objet ne peuvent pas commencer par un nombre, car ils ne peuvent pas être convertis en éléments (XML est même techniquement encore plus strict que cela), mais je peux me débrouiller en cassant certaines des règles de nommage des autres éléments.

N'hésitez pas à mentionner les autres problèmes que vous avez remarqués. J'ai développé mes propres routines personnalisées pour la préparation et le nettoyage des chaînes lors de la conversion. Votre situation peut nécessiter ou non un appel à la préparation/au nettoyage. Comme StaxMan le mentionne, votre situation peut nécessiter une conversion entre objets. Cela peut impliquer des interfaces appropriées et un ensemble d’instructions de cas/etc pour gérer les avertissements que j’ai mentionnés ci-dessus.

38
DaFi4

Vous pouvez également effectuer ces conversions avec le .NET Framework:

JSON en XML: à l'aide de System.Runtime.Serialization.Json

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

XML vers JSON: à l'aide de 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 } };
}
30
Termininja

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
David.Chu.ca

Je ne suis pas sûr que cette conversion soit utile (oui, beaucoup le font, mais surtout pour forcer une cheville carrée à travers un trou rond) - il y a désadaptation des impédances structurelles, et la conversion entraîne des pertes. Je recommande donc de ne pas utiliser de telles transformations de format à format.

Mais si vous le faites, convertissez d’abord json en objet, puis d’objet en xml (et inversement pour l’inverse). La transformation directe entraîne une sortie laide, une perte d'informations, voire les deux.

25
StaxMan

J'ai longtemps cherché un code alternatif à la solution acceptée dans l'espoir de ne pas utiliser un assemblage/projet externe. Je suis arrivé avec ce qui suit grâce au code source du projet 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;
}

Remarque: je voulais un XmlDocument plutôt qu'un XElement aux fins de xPath ..__ De plus, ce code ne va évidemment que du JSON au XML, il y a différentes façons de faire le contraire.

8
yourbuddypal

Voici le code complet c # 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, appelez simplement 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
Nimesh khatri

Essayez cette fonction. Je viens de l'écrire et je n'ai pas vraiment eu l'occasion de le tester, mais mes tests 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
Jamon Crockom

Voici un extrait de code qui convertit (de manière récursive) un XmlNode en une table de hachage et regroupe plusieurs instances du même enfant dans un tableau (sous la forme d'une ArrayList) . bibliothèques.

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
kronenthaler

Pour convertir JSON chaîne en XML essayez ceci:

    public string JsonToXML(string json)
    {
        XDocument xmlDoc = new XDocument(new XDeclaration("1.0", "utf-8", ""));
        XElement root = new XElement("Root");
        root.Name = "Result";

        var dataTable = JsonConvert.DeserializeObject<DataTable>(json);
        root.Add(
                 from row in dataTable.AsEnumerable()
                 select new XElement("Record",
                                     from column in dataTable.Columns.Cast<DataColumn>()
                                     select new XElement(column.ColumnName, row[column])
                                    )
               );


        xmlDoc.Add(root);
        return xmlDoc.ToString();
    }

Pour convertir XML à JSON, essayez ceci:

    public string XmlToJson(string xml)
    {
       XmlDocument doc = new XmlDocument();
       doc.LoadXml(xml);

       string jsonText = JsonConvert.SerializeXmlNode(doc);
       return jsonText;
     }
0
Hasan Fathi

J'ai fait comme David Brown a 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 cela n’est pas toujours nécessaire et, dans le cas d’un flux XML, cela n’est peut-être pas possible. 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 générant l'erreur:

<parent>
    <child>
        Text
    </child>
</parent>
<parent>
    <child>
        <grandchild>
            Text
        </grandchild>
        <grandchild>
            Text
        </grandchild>
    </child>
    <child>
        Text
    </child>
</parent>
0
Ogglas

Cinchoo ETL - une bibliothèque open source disponible pour convertir facilement Xml en JSON 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);
    }
}

Commander CodeProject article pour une aide supplémentaire.

Disclaimer: Je suis l'auteur de cette bibliothèque.

0
RajN

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 nommée Item 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
Sai Ram Sagar