C# Json.NET反序列化JSON为ObservableCollection类型报错
问题原因
异常已经明确给出根因:你调用的接口实际返回的是JSON对象(根节点存在type字段,对应异常提示的Path 'type', line 1, position 8),而非你预期的Video对象数组,因此无法直接反序列化为ObservableCollection<Video>类型。
这类问题绝大多数场景是后端接口做了统一响应包装,比如返回结构为{ "type": 业务状态, "data": 实际Video数组, "message": 提示信息 },而非直接返回数组;剩余场景为请求路径错误、接口报错,返回了错误信息对象。
排查步骤
- 先获取接口真实返回值:在
ReadAsStringAsync执行完成后加断点,或者直接打印result字符串到控制台,不要靠预设的返回结构写反序列化逻辑。 - 校验请求合法性:先判断
responseMessage.IsSuccessStatusCode是否为true,如果接口返回404、400、500等错误状态码,返回内容必然是错误对象,不可能是你要的数组。 - 检查URL拼接逻辑:确认
Base_url和qr参数拼接后地址正确,没有缺路径段、多斜杠、参数格式错误的问题,避免请求到错误的接口。
修复方案
1. 修复服务层请求逻辑
首先给请求加状态码校验,再根据实际返回结构调整反序列化代码。如果接口返回的是统一包装结构,先定义对应的通用响应类:
public class ApiResponse<T> { // 对应异常提示里的type字段 public string Type { get; set; } // 存放实际业务数据的字段,字段名要和接口返回的key完全一致,如果接口返回的key是data就写Data,是result就改对应名 public T Data { get; set; } public string Message { get; set; } }
修改search方法代码:
public async Task<ObservableCollection<Video>> search(string qr) { string url = Base_url + "machines/" + qr; try { // 注意:HttpClient建议全局单例复用,不要每次请求new一个,频繁创建会导致socket耗尽,这里仅保留你原有逻辑做修改 HttpClient client = new HttpClient(); HttpResponseMessage responseMessage = await client.GetAsync(url); // 先判断响应状态 if (!responseMessage.IsSuccessStatusCode) { string errorContent = await responseMessage.Content.ReadAsStringAsync(); Console.WriteLine($"请求失败,状态码:{responseMessage.StatusCode},错误内容:{errorContent}"); return null; } string result = await responseMessage.Content.ReadAsStringAsync(); // 打印实际返回内容方便调试 Console.WriteLine($"接口返回原文:{result}"); // 反序列化为包装对象后取实际数据 var apiResult = JsonConvert.DeserializeObject<ApiResponse<ObservableCollection<Video>>>(result); return apiResult?.Data; // 如果排查后确认接口直接返回数组,把上面两行替换为以下代码即可 // var videoList = JsonConvert.DeserializeObject<ObservableCollection<Video>>(result); // return videoList; } catch(Exception ex) { Console.WriteLine($"请求异常:{ex.Message}\n堆栈:{ex.StackTrace}"); } return null; }
2. 修复View层绑定问题
你当前的Videos属性赋值后没有触发属性变更通知,ListView无法感知数据更新,需要补全PropertyChanged触发逻辑:
public ObservableCollection<Video> Videos { get { return videos; } set { videos = value; // 触发属性变更通知,你的INotifyPropertyChanged接口实现里应该已经有OnPropertyChanged方法,直接调用即可 OnPropertyChanged(nameof(Videos)); } }
3. 字段匹配问题
如果后续反序列化出现部分字段为null的情况,是因为C#属性名和JSON字段名不匹配,可以给对应属性加[JsonProperty("JSON字段名")]特性映射,比如:
public class Video { [Key] [JsonProperty("videoId")] public int VideoId { get; set; } [JsonProperty("exercice")] public string Exercice { get; set; } // 其余字段按相同方式加映射即可 }
内容的提问来源于stack exchange,提问作者Gazdallah Amira
相关产品推荐
相关产品推荐

