Как конвертировать JSON в XML или XML в JSON?

Я начал использовать Json.NET для преобразования строки в формате JSON в объект или наоборот. Я не уверен в структуре Json.NET, можно ли преобразовать строку в JSON в формат XML и наоборот?

Да. Использование classа 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, поэтому ваш пробег может отличаться:

XML -> JSON

  1. Все данные становятся строковыми данными (например, вы всегда будете получать «false», а не false или «0», а не 0 ). Очевидно, что JavaScript обрабатывает их по-разному в определенных случаях.
  2. Элементы-элементы могут стать вложенными-объектами {} ИЛИ вложенными массивами [ {} {} ...] зависимости от того, существует ли только один или несколько элементов-элементов XML. Вы бы потребляли эти два по-разному в JavaScript и т. Д. Различные примеры XML, соответствующие одной и той же схеме, могут создавать фактически разные структуры JSON таким образом. Вы можете добавить атрибут json: Array = ‘true’ к вашему элементу, чтобы обход этого в некоторых (но не обязательно всех) случаях.
  3. Ваш XML должен быть достаточно хорошо сформированным, я заметил, что он не должен полностью соответствовать стандарту W3C, но 1. у вас должен быть корневой элемент и 2. вы не можете начинать имена элементов с номерами, это два из принудительных стандартов XML Я нашел при использовании библиотек Newtonsoft и MS.
  4. Пустые элементы не конвертируются в JSON. Они игнорируются. Пустой элемент не становится «элементом»: null

JSON -> XML

  1. Вам нужен объект верхнего уровня, который будет преобразован в корневой элемент XML, или синтаксический анализатор завершится с ошибкой.
  2. Имена ваших объектов не могут начинаться с числа, поскольку они не могут быть преобразованы в элементы (XML технически даже более строгий, чем этот), но я могу «уйти» с нарушением некоторых правил именования других элементов.

Пожалуйста, не стесняйтесь упоминать какие-либо другие вопросы, которые вы заметили, я разработал свои собственные подпрограммы для подготовки и очистки строк при конвертации туда и обратно. Ваша ситуация может или не может быть вызвана для подготовки / очистки. Как упоминает StaxMan, ваша ситуация может фактически потребовать, чтобы вы конвертировали между объектами … это может повлечь за собой соответствующие интерфейсы и кучу аргументов case / etc для обработки предостережений, о которых я упоминал выше.

Спасибо за ответ Дэвида Брауна. В моем случае JSON.Net 3.5 методы преобразования находятся под статическим classом 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); 

Вы можете сделать эти преобразования также с .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 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 { { xml.Name.LocalName, attr } }; } 

Я не уверен, что есть смысл в таком преобразовании (да, многие это делают, но в основном для принудительной квадратной привязки через круглое отверстие) – существует несоответствие структурного импеданса, а преобразование – с потерями. Поэтому я бы рекомендовал против таких преобразований формата в формат.

Но если вы это сделаете, сначала конвертируйте из json в объект, а затем из объекта в xml (и наоборот для обратного направления). Выполнение прямого преобразования приводит к уродливому выходу, потере информации или, возможно, к тому и другому.

Я долго искал поиск альтернативного кода для принятого решения в надежде не использовать внешнюю сборку / проект. Я придумал следующее благодаря исходному коду проекта 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, есть разные способы сделать обратное.

Вот полный код c # для преобразования xml в 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 childNodeNames = new SortedList(); // 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 alChild = (List)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 childNodeNames, string nodeName, object nodeValue) { // Pre-process contraction of XmlElement-s if (nodeValue is XmlElement) { // Convert  into "aa":null // xx 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 ValuesAL; if (childNodeNames.ContainsKey(nodeName)) { ValuesAL = (List)childNodeNames[nodeName]; } else { ValuesAL = new List(); 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 = " " + "" + "" + "" + "" + "" + ""; 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(""); 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; } 

Вот простой fragment, который преобразует XmlNode (рекурсивно) в хеш-таблицу и группирует несколько экземпляров одного и того же дочернего элемента в массив (как ArrayList). Hashtable обычно принимается для преобразования в JSON большинством библиотек JSON.

 protected object convert(XmlNode root){ Hashtable obj = new Hashtable(); for(int i=0,n=root.ChildNodes.Count;i 

Мне понравился Дэвид Браун, но я получил следующее исключение.

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

Одно из решений заключалось бы в изменении файла XML с помощью корневого элемента, но это не всегда необходимо, и для streamа 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, который генерирует ошибку:

   Text      Text   Text    Text   

Cinchoo ETL – библиотека с открытым исходным кодом, доступная для простого преобразования Xml в JSON с несколькими строками кода

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

Оформить статью CodeProject за дополнительной помощью.

Отказ от ответственности: я являюсь автором этой библиотеки.

  • Текущий узел или узел контекста в XSLT / XPath?
  • Добавление элементов в xml-файл в C #
  • Веб-цвета в файле ресурсов xml-файла для Android
  • Лучший способ кодирования текстовых данных для XML
  • Самый простой способ иметь файл конфигурации в приложении Windows Forms C #
  • Объединить несколько строк в XML?
  • Как создать схему XSD из classа?
  • В чем разница между xsd: include и xsd: import?
  • Почему такая плохая идея анализировать XML с помощью регулярного выражения?
  • Как получить пространства имен в файлах XML с помощью Xpath
  • Как читать XML в .NET?
  • Interesting Posts

    Notepad ++ найти строку с новой строкой и заменить

    Как я могу построить 3D-плоскость в Matlab?

    Вывод первого аргумента шаблона с другими параметрами шаблона по умолчанию

    Добавление полей настраиваемого изображения и других полей одновременно

    MULTIPART_FORM_DATA: не найден источник инъекции для параметра типа public javax.ws.rs.core.Response

    Широковещание при добавлении / изменении контакта?

    Windows 8: как включить «net rpc shutdown»

    Как распечатать любой документ / изображение в файл?

    Ява. Игнорировать акценты при сравнении строк

    Перемещение оси y вверх ногами в MATLAB

    Как я могу использовать SRT для кэширования не загружаемого жесткого диска?

    Загрузить открытый ключ RSA из файла

    Расширенный MySql-запрос: обновить таблицу с информацией из другой таблицы

    Использование mklink / h приводит к тому, что «Доступ запрещен».

    Удобный способ анализа входящих параметров multipart / form-data в Servlet

    Давайте будем гением компьютера.