目前,当我尝试反序列化从 收到的 json 字符串时,我面临以下问题。第三方 (--> 我无法自己更改接收到的 json 字符串)与 Newtonsoft.Json :
json 包含一个字典(以及我未在此处列出的其他一些条目):
"food": {
"Menu 1": "abc",
"Menu 2": "def"
}
我创建了一个包含属性的类(以及我没有在此处列出的属性):
Dictionary<string, string> Food {get; set;}
在这种情况下,json 的反序列化工作正常。
当食物为空时出现问题:
{
"food": [],
}
在这种情况下,食物似乎不是字典而是数组。
这就是反序列化失败并出现以下错误的原因:
Newtonsoft.Json.JsonSerializationException: "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path 'food'."
请问有大佬能帮我解决一下这个问题吗?
编辑
反序列化代码:
public T DeserializeAPIResults<T>(string json)
{
JObject obj = JsonConvert.DeserializeObject<JObject>(json);
return obj.GetValue("canteen").ToObject<T>();
}
编辑 2
带有值的完整 json:
{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi",
"Menu 4": "jkl",
"Menu 5": "mno"
}
},
{
"name": "Canteen2",
"src": "a link",
"food": {
"Menu 1": "abc",
"Menu 2": "def",
"Menu 3": "ghi"
}
},
{
"name": "Canteen3",
"src": "a link",
"food": {
"Line 1": "abc",
"Line 2": "def",
"Line 3": "ghi"
}
}
]
}
没有值的完整 json:
{
"canteen": [
{
"name": "Canteen1",
"src": "a link",
"food": [],
},
{
"name": "Canteen2",
"src": "a link",
"food": [],
},
{
"name": "Canteen3",
"src": "a link",
"food": [],
}
]
}
编辑 3
类:
public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public Dictionary<string, string> Food { get; set; }
public Canteen() { }
}
和方法调用:
Canteen[] canteens = DeserializeAPIResults<Canteen[]>(json);
最佳答案
如果您的特定键的值不固定并且数据必须是可配置的,那么 Newtonsoft.json 有一个可以在这里使用的功能,那就是 [JsonExtensionData]
. Read more
Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.
当您的第 3 方 json 具有名称为
food
的 key 时及其作为对象的值,然后您尝试反序列化为 Dictionary<string, string> Food {get; set;}
并且您的反序列化方法正确反序列化您的 json。但是当
food
键有数组,则您的方法无法反序列化,因为您正在尝试反序列化数组 []
进入 string
.如果你使用
[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
代替
Dictionary<string, string> Food {get; set;}
然后你的反序列化工作。
所以最后你的类(class)将是
public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonExtensionData]
public Dictionary<string, JToken> Food { get; set; }
public Canteen() { }
}
替代:
如果您声明您的
Food
属性数据类型为 JToken
在您的 Canteen
类喜欢public sealed class Canteen
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("food")]
public JToken Food { get; set; }
public Canteen() { }
}
然后你就可以成功反序列化你的 json 无论你的
food
键是对象或数组。然后你可以从 canteens 数组访问你的每个 canteen 并检索每个 canteen 的
name
, src
和 food
键/值对之类的。JToken
的优势是你可以检查它的类型是它的对象还是数组Canteen[] canteens = DeserializeAPIResults<Canteen[]>(json);
foreach (var canteen in canteens)
{
string name = canteen.Name;
string src = canteen.Src;
JToken food = canteen.Food;
if (food.Type == JTokenType.Object)
{
Dictionary<string, string> foods = food.ToObject<Dictionary<string, string>>();
}
else if (food.Type == JTokenType.Array)
{
//Do something if "foods" is empty array "[]"
}
}
关于c# - 当 JSON 字典为空时,反序列化 JSON 字符串失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53458399/