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数组的单个子节点的示例:
我的解决方案:如果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
使用XDocument发现了同样的问题
if(XDocument.Parse(“5.0021.0045.00”)。后代(“row”)。Count()> 1){}
if (XDocument.Parse("1.00 5.00 45.00 |
6.00 10.00 65.00 |
11.00 100.00 98.00 |
").Descendants("row").Count() > 1) { }