【问题标题】:xml to json using newtonsoft issue when loop over array of one element循环遍历一个元素的数组时使用newtonsoft问题将xml转换为json
【发布时间】:2014-01-27 14:04:02
【问题描述】:

只有在源 xml 中只有一个元素的集合时才会出错, 在第一个元素的示例中,我正确地获得了子元素(项目),但在第二个元素中只有一个子元素,因此代码抛出异常(无法访问 Newtonsoft.Json.Linq.JProperty 上的子值)

谢谢

JObject firstLevels = new JObject();
string sourceXML = "<Root>
                        <FirstLevel id=\"1\" name=\"1\">
                            <Item id=\"1\" name=\"1.1\" />
                                <Item id=\"2\" name=\"1.2\" />
                        </FirstLevel>
                        <FirstLevel id=\"2\" name=\"2\">
                            <Item id=\"1\" name=\"2.1\" />
                        </FirstLevel>
                    </Root>";

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sourceXML);
XmlNodeList nodeList;
nodeList = xmlDoc.SelectNodes("Root/FirstLevel");
JArray jarray = new JArray();

foreach (XmlNode node in nodeList)
{
    string json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(node);
    jarray.Add(JObject.Parse(json));
}

firstLevels["result"] = jarray;

foreach(var first in firstLevels["result"].Children<JObject>())
{
    Console.WriteLine(first["FirstLevel"]["@name"].Value<string>());

    foreach (var item in first["FirstLevel"]["Item"])
        Console.WriteLine(" -- " + item["@name"].Value<string>());
}

【问题讨论】:

  • 您可以使用辅助方法来处理这种情况。看我的回答here。

标签: c# xml linq json.net


【解决方案1】:

所以你正在这样做:

string json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(node);

对于这两个节点:

<FirstLevel id=\"1\" name=\"1\">
    <Item id=\"1\" name=\"1.1\" />
        <Item id=\"2\" name=\"1.2\" />
</FirstLevel>

<FirstLevel id=\"2\" name=\"2\">
    <Item id=\"1\" name=\"2.1\" />
</FirstLevel>

现在,在第二种情况下,JSON .Net 无法知道是创建包含单个元素还是仅包含单个元素的集合(即 { a: {}} 或 { a: [{}]})因此它将其转换为单个对象。

不过,这并不是您所期望的。您需要它始终是一个数组以使您的 JSON 保持一致。围绕这些东西已经存在这个问题:JSON.Net Xml Serialization misunderstands arrays 可能值得一读。

因此,我认为您有几个选择:


调整您的 XML 以向 JSON .Net 提供有关做什么的提示

为此,您需要为根节点添加一个命名空间 (xmlns:json='http://james.newtonking.com/projects/json'),并为要参与数组的节点添加一个属性 (json:Array='true')。

例如:

string sourceXML = "<Root xmlns:json='http://james.newtonking.com/projects/json'><FirstLevel id=\"1\" name=\"1\"><Item json:Array='true' id=\"1\" name=\"1.1\" /><Item json:Array='true' id=\"2\" name=\"1.2\" /></FirstLevel><FirstLevel id=\"2\" name=\"2\"><Item json:Array='true' id=\"1\" name=\"2.1\" /></FirstLevel></Root>";

详情请看:http://james.newtonking.com/projects/json/help/?topic=html/ConvertingJSONandXML.html


放入一个虚拟节点以强制 JSON .NET 序列化为数组

我不是很喜欢这个,但是如果你不能调整 XML,把你的代码改成这样就可以了:

foreach (XmlNode node in nodeList)
{        
    string json;
    if (node.SelectNodes("Item").Count == 1)
    {
        // Append a dummy node and then strip it out - horrible!
        node.AppendChild(xmlDoc.CreateNode("element", "Item", ""));
        json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(node).Replace(",null]", "]");
    }
    else
    {
        json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(node);                    
    }

    jarray.Add(JObject.Parse(json));
}

阅读时检查

当然,您可以在处理数据时只检查类型,如下所示:

foreach (var first in firstLevels["result"].Children<JObject>())
{
    Console.WriteLine(first["FirstLevel"]["@name"].Value<string>());

    if (first["FirstLevel"]["Item"] is Newtonsoft.Json.Linq.JObject)
    {
        Console.WriteLine(" -- " + first["FirstLevel"]["Item"]["@name"].Value<string>());
    }
    else
    {
        foreach (var item in first["FirstLevel"]["Item"])
            Console.WriteLine(" -- " + item["@name"].Value<string>());
    }
}

【讨论】:

    【解决方案2】:

    你不需要手动做这个 xml 到 json 的转换

    string sourceXML = "<Root><FirstLevel id=\"1\" name=\"1\"><Item id=\"1\" name=\"1.1\" /><Item id=\"2\" name=\"1.2\" /></FirstLevel><FirstLevel id=\"2\" name=\"2\"><Item id=\"1\" name=\"2.1\" /></FirstLevel></Root>";
    
    var json = JsonConvert.SerializeObject(XDocument.Parse(sourceXML));
    

    或者获取一个json数组

    var json2 = JsonConvert.SerializeObject(XDocument.Parse(sourceXML)
                                                     .Descendants("FirstLevel"));
    

    【讨论】:

      猜你喜欢
      • 2018-03-13
      • 2021-08-12
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      • 2021-11-08
      • 1970-01-01
      相关资源
      最近更新 更多