如何编写通用JSON反序列化方法?解决Newtonsoft.Json序列化异常
JSON反序列化错误解决方法
错误信息
Newtonsoft.Json.JsonSerializationException: '无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Collections.Generic.IEnumerable`1[ClientAddressWFA.Models.Address]',因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。
要修复此错误,请将JSON改为JSON数组(例如[1,2,3]),或者更改反序列化类型,使其成为可从JSON对象反序列化的普通.NET类型(例如不是整数等基元类型,也不是数组或List等集合类型)。也可以向该类型添加JsonObjectAttribute以强制其从JSON对象反序列化。
通用反序列化方法代码
public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri) { HttpClient client = new HttpClient(); HttpResponseMessage response = await client.GetAsync(uri); var content = await response.Content.ReadAsStreamAsync(); StreamReader reader = new StreamReader(content); JsonReader jReader = new JsonTextReader(reader); JsonSerializer jSer = new JsonSerializer(); return jSer.Deserialize<IEnumerable<T>>(jReader); }
API响应结构
API返回的是一个FeatureCollection对象,而非直接的地址数组,结构大致如下:
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { /* 对应Address模型的字段数据 */ }, /* 其他无关字段 */ } ] }
Address模型代码
public class Address { [JsonProperty("id")] public int Id; [JsonProperty("streetAddress")] public int StreetAddress; [JsonProperty("streetName")] public string StreetName; [JsonProperty("buildingNumber")] public int BuildingNumber; [JsonProperty("additionalBuildingNumber")] public string AdditionalBuildingNumber; [JsonProperty("fullAddress")] public string FullAddress; [JsonProperty("zipCode")] public int ZipCode; [JsonProperty("coordinateX")] public double CoordinateX; [JsonProperty("coordinateY")] public double CoordinateY; [JsonProperty("sozraum")] public int Sozraum; [JsonProperty("sozialraum")] public int Sozialraum; [JsonProperty("lebraum")] public int Lebraum; [JsonProperty("lebensraum")] public int Lebensraum; [JsonProperty("stimmbezirk")] public int Stimmbezirk; [JsonProperty("hnr_nur_fb62")] public string HnrNurFb62; [JsonProperty("gerade")] public string Gerade; [JsonProperty("district")] public string District; [JsonProperty("districtNumber")] public string DistrictNumber; [JsonProperty("wkb_geometry")] public string WkbGeometry; [JsonProperty("isMain")] public bool IsMain; }
解决方案
方法1:创建匹配API响应的根模型
新增两个类适配API响应结构:
public class FeatureCollection { [JsonProperty("features")] public List<Feature> Features { get; set; } } public class Feature { [JsonProperty("properties")] public Address Properties { get; set; } }
调用时先反序列化为FeatureCollection,再提取地址集合:
var featureCollection = await JsonDeserialize<FeatureCollection>(uri); IEnumerable<Address> addresses = featureCollection.Features.Select(f => f.Properties);
方法2:直接解析JSON对象提取数组
无需新增模型,修改反序列化方法直接提取目标数组:
public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri) { using HttpClient client = new HttpClient(); HttpResponseMessage response = await client.GetAsync(uri); string json = await response.Content.ReadAsStringAsync(); JObject jsonObj = JObject.Parse(json); JArray featuresArray = (JArray)jsonObj["features"]; return featuresArray.Select(f => f["properties"].ToObject<T>()); }
核心错误原因
原方法试图将整个JSON对象直接反序列化为集合类型,但API返回的是包含数组的外层对象,而非数组本身,导致序列化失败。
内容的提问来源于stack exchange,提问作者Goga Gate
相关产品推荐
相关产品推荐

