Newtonsoft.Json反序列化失败:模型匹配错误求助
问题场景
使用Newtonsoft.Json从API下载数据时,调用DeserializeObject出现反序列化错误,怀疑ObjectResponse模型构建存在问题,需修正模型及相关代码。
API返回的JSON内容
{"success":true,"data":{"leasingItems":[],"suspectedItems":[]}}
现有控制器代码
private async Task<Response<IEnumerable<ObjectResponse>>> GetItemsAsync(string uri) { var result = await _client.GetStringAsync(uri); return JsonConvert.DeserializeObject<Response<IEnumerable<ObjectResponse>>>(result); }
现有模型代码
public class Response<T> { public bool Success { get; set; } public T Data { get; set; } public IEnumerable<Error> Errors { get; set; } } public class ObjectResponse { public string[]? leasingItems { get; set; } public string[]? suspectedItems { get; set; } }
错误信息(中文翻译)
发生一个或多个错误。(无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Collections.Generic.IEnumerable`1[Swip.Core.DTO.SwipSearchSuspect]',因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。
要修复此错误,请将JSON更改为JSON数组(例如[1,2,3]),或者更改反序列化类型,使其成为可以从JSON对象反序列化的普通.NET类型(例如不是整数等基元类型,不是数组或List等集合类型)。也可以向类型添加JsonObjectAttribute以强制其从JSON对象反序列化。
路径'data.leasingItems',第1行,位置39。)
内部异常1:
JsonSerializationException: 无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Collections.Generic.IEnumerable`1[Swip.Core.DTO.SwipSearchSuspect]',因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。
要修复此错误,请将JSON更改为JSON数组(例如[1,2,3]),或者更改反序列化类型,使其成为可以从JSON对象反序列化的普通.NET类型(例如不是整数等基元类型,不是数组或List等集合类型)。也可以向类型添加JsonObjectAttribute以强制其从JSON对象反序列化。
路径'data.leasingItems',第1行,位置39。
修复方案
核心问题分析
当前代码中,泛型Response<T>的T被指定为IEnumerable<ObjectResponse>,即期望API返回的data是一个对象数组,但实际API返回的data是一个单一对象,该对象包含leasingItems和suspectedItems两个数组字段,类型不匹配导致反序列化失败。
具体修改步骤
- 调整控制器的返回类型与反序列化目标类型
将Response<IEnumerable<ObjectResponse>>改为Response<ObjectResponse>,匹配API返回的data结构:
private async Task<Response<ObjectResponse>> GetItemsAsync(string uri) { var result = await _client.GetStringAsync(uri); return JsonConvert.DeserializeObject<Response<ObjectResponse>>(result); }
- 修正模型的属性映射(可选但推荐)
C#属性默认使用PascalCase命名,而JSON字段使用camelCase,需确保命名匹配。可通过两种方式解决:
方式1:添加JsonProperty特性
public class Response<T> { [JsonProperty("success")] public bool Success { get; set; } [JsonProperty("data")] public T Data { get; set; } [JsonProperty("errors")] public IEnumerable<Error> Errors { get; set; } } public class ObjectResponse { [JsonProperty("leasingItems")] public List<string>? LeasingItems { get; set; } // 推荐用List而非数组,更灵活 [JsonProperty("suspectedItems")] public List<string>? SuspectedItems { get; set; } }
方式2:配置全局序列化规则
如果不想逐个添加特性,可在反序列化时指定驼峰命名解析器:
private async Task<Response<ObjectResponse>> GetItemsAsync(string uri) { var result = await _client.GetStringAsync(uri); var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; return JsonConvert.DeserializeObject<Response<ObjectResponse>>(result, settings); }
验证修改
修改完成后,重新调用接口即可正常反序列化JSON数据,错误将被解决。
内容的提问来源于stack exchange,提问作者Michael1834

