سؤال

لقد بدأت في استخدام Json.NET لتحويل سلسلة بتنسيق JSON إلى كائن أو العكس.لست متأكدًا في إطار عمل Json.NET، هل من الممكن تحويل سلسلة بتنسيق JSON إلى تنسيق XML والعكس؟

هل كانت مفيدة؟

المحلول

نعم.استخدام فئة 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);

التوثيق هنا: التحويل بين JSON وXML باستخدام Json.NET

نصائح أخرى

نعم انت يستطيع افعل ذلك (أفعل) ولكن كن على دراية ببعض المفارقات عند التحويل، وتعامل معها بشكل مناسب.لا يمكنك التوافق تلقائيًا مع جميع إمكانيات الواجهة، كما أن هناك دعمًا مدمجًا محدودًا للتحكم في التحويل - لا يمكن تحويل العديد من هياكل وقيم JSON تلقائيًا في كلا الاتجاهين.ضع في اعتبارك أنني أستخدم الإعدادات الافتراضية مع مكتبة Newtonsoft JSON ومكتبة MS XML، لذا قد يختلف عدد الأميال المقطوعة:

إكس إم إل -> جيسون

  1. تصبح جميع البيانات بيانات سلسلة (على سبيل المثال، ستحصل دائمًا على "خطأ شنيع" لا خطأ شنيع أو "0" لا 0) من الواضح أن جافا سكريبت تتعامل مع هذه الأمور بشكل مختلف في بعض الحالات.
  2. يمكن أن تصبح العناصر الفرعية كائنًا متداخلاً {} أو مصفوفة متداخلة [ {} {} ...] اعتمادًا على ما إذا كان هناك عنصر فرعي واحد أو أكثر من عناصر XML.سوف تستهلك هذين الاثنين بشكل مختلف في JavaScript، وما إلى ذلك.يمكن لأمثلة مختلفة من XML المطابقة لنفس المخطط أن تنتج هياكل JSON مختلفة بالفعل بهذه الطريقة.يمكنك إضافة السمة جسون: صفيف = "صحيح" إلى العنصر الخاص بك لحل هذه المشكلة في بعض الحالات (ولكن ليس بالضرورة جميعها).
  3. يجب أن يكون XML الخاص بك تماما جيدة التكوين، لقد لاحظت أنها لا تحتاج إلى التوافق تمامًا مع معيار W3C، ولكن 1.يجب أن يكون لديك عنصر جذر و 2.لا يمكنك بدء أسماء العناصر بالأرقام، وهما اثنان من معايير XML المفروضة التي وجدتها عند استخدام مكتبات Newtonsoft وMS.
  4. في الإصدارات الأقدم، لا يتم تحويل العناصر الفارغة إلى JSON.يتم تجاهلهم.لا يصبح عنصر فارغ "العنصر":خالي

تحديث جديد يغير هذا (شكرًا لـ Jon Story للإشارة إلى ذلك): https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm

جيسون -> إكس إم إل

  1. أنت بحاجة إلى كائن المستوى الأعلى الذي سيتم تحويله إلى عنصر XML الجذري وإلا سيفشل المحلل اللغوي.
  2. لا يمكن أن تبدأ أسماء الكائنات الخاصة بك برقم، حيث لا يمكن تحويلها إلى عناصر (XML أكثر صرامة من الناحية الفنية من هذا) ولكن يمكنني "الإفلات" من كسر بعض قواعد تسمية العناصر الأخرى.

لا تتردد في ذكر أي مشاكل أخرى لاحظتها، لقد قمت بتطوير إجراءاتي المخصصة لإعداد وتنظيف السلاسل أثناء التحويل ذهابًا وإيابًا.قد يتطلب وضعك أو لا يتطلب الاستعداد/التنظيف.كما ذكر StaxMan، قد يتطلب موقفك في الواقع التحويل بين الكائنات... وقد يستلزم ذلك واجهات مناسبة ومجموعة من بيانات الحالة/إلخ للتعامل مع التحذيرات التي ذكرتها أعلاه.

يمكنك إجراء هذه التحويلات أيضًا باستخدام .NET Framework:

JSON إلى XML: باستخدام System.Runtime.Serialization.Json

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

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

وأنا لست متأكد من أن هناك نقطة في هذا التحويل (نعم، كثير تفعل ذلك، ولكن في الغالب لفرض ربط مربع من خلال حفرة مستديرة) - هناك عدم تطابق مقاومة الهيكلي، والتحويل الضياع. لذلك أنصح ضد مثل هذه التحولات شكل إلى شكل.

ولكن إذا كنت تفعل ذلك، أولا تحويل من سلمان في الاعتراض، ثم من كائن إلى XML (والعكس صحيح بالنسبة الاتجاه المعاكس). فعل التحول المباشر يؤدي إلى إخراج القبيح، وفقدان المعلومات، أو ربما على حد سواء.

وشكرا لإجابة ديفيد براون. في حالتي من 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);

وأنا بحثت عن وقتا طويلا للعثور على رمز بديل إلى حل مقبول على أمل عدم استخدام التجميع / مشروع خارجي. خطرت لي ذلك بفضل التالية إلى رمز مصدر 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;
}

ملحوظة: كنت أرغب في XmlDocument بدلا من XElement لأغراض xPath المتوفر. أيضا، هذا الرمز الواضح يذهب فقط من JSON إلى XML، وهناك طرق مختلفة لتفعل العكس.

وهنا هو الكامل ج # رمز لتحويل XML لسلمان

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

لتحويل سلسلة 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" }}

جرب هذه الوظيفة. أنا فقط كتبت ذلك وليس لديه الكثير من فرصة لاختبار ذلك، ولكن بلدي التجارب الأولية واعدة.

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

وهنا عبارة عن مقتطف بسيط يحول XmlNode (متكرر) في جدول هاش، والجماعات مثيلات متعددة من نفس الطفل في صفيف (باعتبارها ArrayList). يتم قبول جدول هاش عادة تحويلها إلى JSON من قبل معظم المكتبات 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;
}

وفعلت مثلما قال ديفيد براون لكني حصلت على الاستثناء التالي.

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

وحل واحد سيكون لتعديل ملف 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);
            }
        }
    }
}

مثال XML التي تنشئ الخطأ:

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

Cinchoo ETL - مكتبة مفتوحة المصدر المتاحة للقيام تحويل XML إلى JSON بسهولة مع الأسطر القليلة من التعليمات البرمجية

وأكس -> 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);
    }
}

والمادة الخروج CodeProject لبعض المساعدات الاضافية.

تنويه: أنا صاحب هذا مكتبة

ولقد استخدمت الأساليب التالية لتحويل JSON إلى 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();
            }
        }

و

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

ولقد استخدمت فئة المسمى البند لتمثيل العناصر

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

    }

وكان يعمل ....

لسلسلة تحويل JSON إلى XML حاول هذا:

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

لتحويل XML إلى JSON حاول هذا:

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

       string jsonText = JsonConvert.SerializeXmlNode(doc);
       return jsonText;
     }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top