我使用DataContractJsonSerializer将json字符串解析为对象hierarchie。 json字符串如下所示:
{
"groups": [
{
"attributes": [
{
"sortOrder": "1",
"value": "A"
},
{
"sortOrder": "2",
"value": "B"
}
]
},
{
"attributes": {
"sortOrder": "1",
"value": "C"
}
}
]
}
正如您所看到的,“属性”的子值可以是数组或单个项目。 我找到了问题发生的代码部分:
[DataContract]
public class ItemGroup
{
[DataMember(Name="attributes")]
public List<DetailItem> Items { get; set; }
}
这适用于第一个但未通过第二个。
有人对此有答案吗?
THX
答案 0 :(得分:3)
如果您控制JSON的创建方式,那么即使它只包含一个元素,也要确保属性是一个数组。然后第二个元素看起来像这样并解析得很好。
{
"attributes": [{
"sortOrder": "1",
"value": "C"
}]
}
答案 1 :(得分:3)
正如Daniel所说,如果你可以控制Json的创建,那么最好继续这样做。 但是,如果你不能,那么你可以使用Json.Net库&amp;来自的JsonObject类 this链接写一些代码,如:
JObject o = (JObject)JsonConvert.DeserializeObject(input);
dynamic json = new JsonObject(o);
foreach (var x in json.groups)
{
var attrs = x.attributes;
if (attrs is JArray)
{
foreach (var y in attrs)
{
Console.WriteLine(y.value);
}
}
else
{
Console.WriteLine(attrs.value);
}
}
答案 2 :(得分:1)
我尝试使用DataContractJsonSerializer,JavaScriptSerializer和JSON.Net,并且没有人会在所有情况下成功直接反序列化到对象。我使用类似的方法作为L.B,使用JSON.Net,虽然没有使用动力学和额外的JsonObject类。使我的代码适应您的场景将如下所示:
private List<ItemGroup> ParseItemGroupList(string input)
{
JObject json = JObject.Parse(input);
List<ItemGroup> groups = new List<ItemGroup>();
JArray gArray = json["groups"] as JArray;
foreach (var gToken in gArray)
{
ItemGroup newGroup = new ItemGroup();
JToken attrToken = gToken["attributes"] as JToken;
if (attrToken is JArray)
{
newGroup.Items = attrToken.Children().Select(MapDetailItem()).ToList();
}
else
{
newGroup.Items = new List<DetailItem>() { MapDetailItem().Invoke(attrToken) };
}
groups.Add(newGroup);
}
return groups;
}
private static Func<JToken, DetailItem> MapDetailItem()
{
return json => new DetailItem
{
SortOrder = (string)json["sortOrder"],
Value = (string)json["value"]
};
}
希望有人会为JSON.Net添加一个设置,以允许它强制反序列化到具有单个项目的集合,而不是抛出异常。遗憾的是,当只有一小部分JSON无法自动解析时,您必须手动执行所有解析。