JSON.Net Xml序列化误解了数组

我有一些自动生成的xmls,其中xml的某些部分可能有多行,有些可能没有。 结果是,如果有一行返回一个json节点,并且如果我有多行,则返回一个带有json节点的数组。

xmls可能看起来像这样

   Testing 0      

或者有多行

    Update Documentation 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" }] } } } 

可以清楚地看到第二个上的Row是一个数组应该是但不在第一个上。 有没有关于这类问题的已知解决方法,或者我需要在接收JSON的前端实现检查(由于结构非常动态,这会有点问题)。 最好的方法是,如果有任何方法强制json.net始终返回数组。

来自Json.NET文档: http ://james.newtonking.com/projects/json/help/?topic = html /ConvertingJSONandXML.htm

通过将属性json:Array='true'到要转换为JSON的XML节点,可以强制将节点呈现为Array。 此外,您需要在XML标头xmlns:json='http://james.newtonking.com/projects/json'声明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); } 

它有点脏,但它的工作原理。 我仍然对其他解决方案感兴趣!

给IvánPérezGómez我+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”)。后代(“row”)。Count()> 1){}

  if (XDocument.Parse("1.005.0045.006.0010.0065.0011.00100.0098.00").Descendants("row").Count() > 1) { }