只有在源xml中只有一个元素的集合时才会出错 在第一个元素的示例中,我正确获得子元素(item),但在第二个元素中只有一个子元素,因此代码抛出异常(无法访问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>());
}
答案 0 :(得分:2)
所以你这样做:
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>());
}
}
答案 1 :(得分:0)
您无需手动执行此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"));