无法将 JSON 数组反序列化为类型 - Json.NET
Posted
技术标签:
【中文标题】无法将 JSON 数组反序列化为类型 - Json.NET【英文标题】:Cannot deserialize JSON array into type - Json.NET 【发布时间】:2012-03-16 05:03:23 【问题描述】:我正在尝试将 json 数据反序列化为模型类,但我失败了。这是我的工作:
public CountryModel GetCountries()
using (WebClient client = new WebClient())
var result = client.DownloadString("http://api.worldbank.org/incomeLevels/LIC/countries?format=json");
var output = JsonConvert.DeserializeObject<List<CountryModel>>(result);
return output.First();
这是我的模型的样子:
public class CountryModel
public int Page get; set;
public int Pages get; set;
public int Per_Page get; set;
public int Total get; set;
public List<Country> Countries get; set;
public class Country
public int Id get; set;
public string Iso2Code get; set;
public string Name get; set;
public Region Region get; set;
public class Region
public int Id get; set;
public string Value get; set;
你可以看到我在这里得到的 Json:http://api.worldbank.org/incomeLevels/LIC/countries?format=json
这是我得到的错误:
无法将 JSON 数组反序列化为“Mvc4AsyncSample.Models.CountryModel”类型。第 1 行,位置 1。
【问题讨论】:
这似乎不是一个好的 JSON 表示。如果你使用 XML 格式可能会更好。 是的,我想是的。他们将单个对象放入数组中。我认为它不应该在那里。有什么可行的方法吗? XML 更加简洁,我会这样做:api.worldbank.org/incomeLevels/LIC/countries?format=xml @PaulTyng 我认为,AFAIK,Json.NET 序列化比 .NET XML 序列化快得多。这就是我坚持使用 JSON 的原因。但我不确定我在这里是否 100% 正确。 @tugberk 啊,我明白了,如果您关心速度,尽管您可能想查看其他 JSON 库:theburningmonk.com/2011/08/performance-test-json-serializers(或 code.google.com/p/protobuf-net) 【参考方案1】:你要写一个自定义的JsonConverter
:
public class CountryModelConverter : JsonConverter
public override bool CanConvert(Type objectType)
if (objectType == typeof(CountryModel))
return true;
return false;
public override object ReadJson(JsonReader reader, Type objectType
, object existingValue, JsonSerializer serializer)
reader.Read(); //start array
//reader.Read(); //start object
JObject obj = (JObject)serializer.Deserialize(reader);
//"page":1,"pages":1,"per_page":"50","total":35
var model = new CountryModel();
model.Page = Convert.ToInt32(((JValue)obj["page"]).Value);
model.Pages = Convert.ToInt32(((JValue)obj["pages"]).Value);
model.Per_Page = Int32.Parse((string) ((JValue)obj["per_page"]).Value);
model.Total = Convert.ToInt32(((JValue)obj["total"]).Value);
reader.Read(); //end object
model.Countries = serializer.Deserialize<List<Country>>(reader);
reader.Read(); //end array
return model;
public override void WriteJson(JsonWriter writer, object value
, JsonSerializer serializer)
throw new NotImplementedException();
并使用该转换器标记CountryModel
(我还必须将一些int
切换为string
):
[JsonConverter(typeof(CountryModelConverter))]
public class CountryModel
public int Page get; set;
public int Pages get; set;
public int Per_Page get; set;
public int Total get; set;
public List<Country> Countries get; set;
public class Country
public string Id get; set;
public string Iso2Code get; set;
public string Name get; set;
public Region Region get; set;
public class Region
public string Id get; set;
public string Value get; set;
那么你应该可以像这样反序列化:
var output = JsonConvert.DeserializeObject<CountryModel>(result);
【讨论】:
你不能通过使用serializer.Deserialize<CountryModel>(reader)
来简化反序列化CountryModel
的属性吗?
如果您只需要阅读,svick 的答案会更好,JsonConverter
只有在您必须双向使用时才真正需要。
@svick 我想了想,问题是CountryModel
有这个属性,所以它进入了无限循环,如果对象模型改变了,它会被简化,但我试图保持他的对象模型。
对,我没想到。【参考方案2】:
这看起来像是(不是很好)用 JSON 表示 XML 的尝试。 JSON 如下所示:
[
"page": 1,
…
,
[
"id": "AFG",
"name": "Afghanistan",
…
,
"id": "BDI",
"name": "Burundi",
…
,
…
]
]
虽然一个合理的 JSON(顺便说一句会很好地映射到您的模型)看起来像这样:
"page": 1,
…,
"countries": [
"id": "AFG",
"name": "Afghanistan",
…
,
"id": "BDI",
"name": "Burundi",
…
,
…
]
如果您确定要使用 JSON(而不是 XML),您可以先将 JSON 反序列化为 JSON.NET 的对象模型,然后将其反序列化为您的模型:
var json = client.DownloadString("http://api.worldbank.org/incomeLevels/LIC/countries?format=json");
var array = (JArray)JsonConvert.DeserializeObject(json);
var serializer = new JsonSerializer();
var countryModel = serializer.Deserialize<CountryModel>(array[0].CreateReader());
countryModel.Countries = serializer.Deserialize<List<Country>>(array[1].CreateReader());
return countryModel;
不要忘记将您的 Id
属性更改为 string
,因为它们就是这样。
【讨论】:
比我的版本简单得多,很好,不知道你可以创建阅读器的内置对象。【参考方案3】:您的模型与 JSON 结构不匹配。您似乎缺少最后 6 个属性。
"id": "AFG",
"iso2Code": "AF",
"name": "Afghanistan",
"region":
"id": "SAS",
"value": "South Asia"
,
"adminregion":
"id": "SAS",
"value": "South Asia"
,
"incomeLevel":
"id": "LIC",
"value": "Low income"
,
"lendingType":
"id": "IDX",
"value": "IDA"
,
"capitalCity": "Kabul",
"longitude": "69.1761",
"latitude": "34.5228"
【讨论】:
这不会影响反序列化过程。以上是关于无法将 JSON 数组反序列化为类型 - Json.NET的主要内容,如果未能解决你的问题,请参考以下文章
无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“ConsoleAppTest01.Location”,因为该类型需要 JSON 对象
WinForms 错误无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型
无法将 JSON 数组(例如 [1,2,3])反序列化为类型 ' ',因为类型需要 JSON 对象(例如 "name":"value")才能正确反序列化
无法将 JSON 数组(例如 [1,2,3])反序列化为类型 ' ',因为类型需要 JSON 对象(例如 "name":"value")才能正确反序列化
无法将 JSON 数组(例如 [1,2,3])反序列化为类型 ' ',因为类型需要 JSON 对象(例如 "name":"value")来反序列化 withGe