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

Eri*_*itz 24 c# json json.net

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

xmls可能看起来像这样

<List>
    <Content>
        <Row Index="0">
            <Title>Testing</Title>
            <PercentComplete>0</PercentComplete>
            <DueDate/>
            <StartDate/>
        </Row>
    </Content>
</List>
Run Code Online (Sandbox Code Playgroud)

或者有多行

<List>
    <Content>
        <Row Index="0">
            <Title>Update Documentation</Title>
            <PercentComplete>0.5</PercentComplete>
            <DueDate>2013-01-31 00:00:00</DueDate>
            <StartDate>2013-01-01 00:00:00</StartDate>
        </Row>
        <Row Index="1">
            <Title>Write jQuery example</Title>
            <PercentComplete>0.05</PercentComplete>
            <DueDate>2013-06-30 00:00:00</DueDate>
            <StartDate>2013-01-02 00:00:00</StartDate>
        </Row>
    </Content>
</List>
Run Code Online (Sandbox Code Playgroud)

使用时将这些序列化为JSON

JsonConvert.SerializeXmlNode(xmldoc, Formatting.Indented);
Run Code Online (Sandbox Code Playgroud)

第一个xml变成了这个

{
    "List": {
        "Content": {
            "Row": {
                "@Index": "0",
                "Title": "Testing",
                "PercentComplete": "0",
                "DueDate": null,
                "StartDate": null
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个这个

{
    "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"
            }]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Ivá*_*mez 23

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

您可以通过将属性添加json:Array='true'到要转换为JSON的XML节点来强制将节点呈现为Array .此外,您需要在XML标头处声明json前缀命名空间,xmlns:json='http://james.newtonking.com/projects/json'否则您将收到一条XML错误,指出未声明json前缀.

下一个示例由文档提供:

xml = @"<person xmlns:json='http://james.newtonking.com/projects/json' id='1'>
        <name>Alan</name>
        <url>http://www.google.com</url>
        <role json:Array='true'>Admin</role>
      </person>";
Run Code Online (Sandbox Code Playgroud)

生成的输出:

{
  "person": {
    "@id": "1",
    "name": "Alan",
    "url": "http://www.google.com",
    "role": [
      "Admin"
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*itz 10

我确实解决了这种行为

// 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);
}
Run Code Online (Sandbox Code Playgroud)

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


Sta*_*nko 8

给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);
    }
Run Code Online (Sandbox Code Playgroud)

并将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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

以下是作为json数组的单个子节点的示例:

以下是作为json数组的单个子节点的示例: