JSON.Net Xml Сериализация неправильно понимает массивы

У меня есть некоторые автогенерируемые xmls, где некоторые части xml могут иметь несколько строк, а некоторые – нет. В результате, если есть одна строка, возвращается один json-узел, и если у меня есть несколько строк, возвращается массив с json-узлами.

Xmls может выглядеть так:

   Testing 0      

Или с несколькими строками

    Update Do<a href="https://www.bilee.com/key/c" title="View all posts in c" target="_blank">c</a>umentation 0.5 2013-01-31 00:00:00 2013-01-01 00:00:00   Write jQuery example 0.05 2013-06-30 00:00:00 2013-01-02 00:00:00    

При их сериализации с использованием JSON

 JsonConvert.SerializeXmlNode(xmldoc, Formatting.Indented); 

Первый xml становится

 { "List": { "Content": { "Row": { "@Index": "0", "Title": "Testing", "PercentComplete": "0", "DueDate": null, "StartDate": null } } } } 

И второе

 { "List": { "Content": { "Row": [{ "@Index": "0", "Title": "Update Documentation", "PercentComplete": "0.5", "DueDate": "2013-01-31 00:00:00", "StartDate": "2013-01-01 00:00:00" }, { "@Index": "1", "Title": "Write jQuery example", "PercentComplete": "0.05", "DueDate": "2013-06-30 00:00:00", "StartDate": "2013-01-02 00:00:00" }] } } } 

Как ясно видно, строка на втором является массивом, который должен быть, но не первым. Существует ли какое-либо известное обходное решение для такого рода проблем или мне нужно выполнить проверку в моем интерфейсе, получая JSON (это было бы немного проблематично, поскольку структуры очень динамичны). Лучше всего было бы, если бы там, где любой способ принудить json.net всегда возвращать массивы.

Из документации Json.NET: http://james.newtonking.com/projects/json/help/?topic=html/ConvertingJSONandXML.htm

Вы можете заставить узел быть рендером в виде массива, добавив атрибут json:Array='true' к узлу XML, который вы конвертируете в JSON. Кроме того, вам нужно объявить пространство имен префиксов json в заголовке XML xmlns:json='http://james.newtonking.com/projects/json' иначе вы получите сообщение об ошибке XML, в котором указано, что префикс json не объявлен.

Следующий пример представлен документацией:

 xml = @" Alan http://www.google.com Admin "; 

Сгенерированный выход:

 { "person": { "@id": "1", "name": "Alan", "url": "http://www.google.com", "role": [ "Admin" ] } } 

Я исправил это поведение, как это

 // Handle JsonConvert array bug var rows = doc.SelectNodes("//Row"); if(rows.Count == 1) { var contentNode = doc.SelectSingleNode("//List/Content"); contentNode.AppendChild(doc.CreateNode("element", "Row", "")); // Convert to JSON and replace the empty element we created but keep the array declaration returnJson = JsonConvert.SerializeXmlNode(doc).Replace(",null]", "]"); } else { // Convert to JSON returnJson = JsonConvert.SerializeXmlNode(doc); } 

Это немного грязно, но это работает. Меня все еще интересуют другие решения!

Предоставляя мой +1 Ивану Пересу Гомесу и предоставляя код здесь, чтобы поддержать его ответ:

Добавьте требуемое пространство имен json.net в корневой узел:

 private static void AddJsonNetRootAttribute(XmlDocument xmlD) { XmlAttribute jsonNS = xmlD.CreateAttribute("xmlns", "json", "http://www.w3.org/2000/xmlns/"); jsonNS.Value = "http://james.newtonking.com/projects/json"; xmlD.DocumentElement.SetAttributeNode(jsonNS); } 

И добавить атрибут json: Array к элементам, найденным xpath:

 private static void AddJsonArrayAttributesForXPath(string xpath, XmlDocument doc) { var elements = doc.SelectNodes(xpath); foreach (var element in elements) { var el = element as XmlElement; if (el != null) { var jsonArray = doc.CreateAttribute("json", "Array", "http://james.newtonking.com/projects/json"); jsonArray.Value = "true"; el.SetAttributeNode(jsonArray); } } } 

Вот пример одного дочернего узла как json-массив:

Вот пример одного дочернего узла как json-массив:

Мое решение: если JsonConvert не работает, не используйте его. Разбирайте XML в словари / коллекции, а затем в Json. По крайней мере, таким образом вам не нужно жестко кодировать любые имена элементов.

  private JsonResult AsJsonResult(XmlDocument result) { var kvp = new KeyValuePair(result.DocumentElement.Name, Value(result.DocumentElement)); return Json(kvp , JsonRequestBehavior.AllowGet); } ///  /// Deserializing straight from Xml produces Ugly Json, convert to Dictionaries first to strip out unwanted nesting ///  ///  ///  private object Value(XmlNode node) { dynamic value; //If we hit a complex element if (node.HasChildNodes && !(node.FirstChild is XmlText)) { //If we hit a collection, it will have children which are also not just text! if (node.FirstChild.HasChildNodes && !(node.FirstChild.FirstChild is XmlText)) { //want to return a list of Dictionarys for the children's nodes //Eat one level of the hierachy and return child nodes as an array value = new List(); foreach (XmlNode childNode in node.ChildNodes) { value.Add(Value(childNode)); } } else //regular complex element return childNodes as a dictionary { value = new Dictionary(); foreach (XmlNode childNode in node.ChildNodes) { value.Add(childNode.Name, Value(childNode)); } } } else //Simple element { value = node.FirstChild.InnerText; } return value; } 

Обнаружена такая же проблема с использованием XDocument

if (XDocument.Parse («5.0021.0045.00»). Потомки («строка»). Count ()> 1) {}

  if (XDocument.Parse("1.005.0045.006.0010.0065.0011.00100.0098.00").Descendants("row").Count() > 1) { } 
  • Deserialize json, который имеет некоторое имя свойства, начиная с числа
  • Сериализовать контейнер перечислений в виде строк с помощью JSON.net
  • Объединение двух массивов Json.NET путем конкатенации содержащихся элементов
  • Как изменить имена свойств при сериализации с помощью Json.net?
  • Исключение «Исключительная привязка к реляционной ссылке» с JSON.Net
  • JToken: получить исходное / оригинальное значение JSON
  • Дезаминирование гетерогенного массива JSON в ковариантный список с использованием JSON.NET
  • Разбор большого json-файла в .NET.
  • JSON.NET и nHibernate Lazy Загрузка коллекций
  • Обеспечение json-ключей в .NET
  • Каков правильный способ использования JSON.NET для анализа streamа объектов JSON?
  • Давайте будем гением компьютера.