[c#] كيفية تحويل JSON إلى XML أو XML إلى JSON؟



Answers

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

XML -> JSON

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

JSON -> XML

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

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

Question

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




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




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

$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>



يمكنك إجراء هذه التحويلات أيضًا مع .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 } };
}



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

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



Links