如何将API返回的JSON反序列化为List?遇Newtonsoft序列化异常
问题解决:JSON反序列化异常及异步调用问题
核心错误分析
- 反序列化类型不匹配:目标API返回的JSON结构是一个包含
coins数组的单个对象,而非List<Root>集合。你试图将其反序列化为List<Root>,这直接触发JsonSerializationException。 - 异步方法设计错误:使用
async void会导致无法追踪异步操作完成状态,且异常无法被捕获;同时按值传递List<Root>参数,方法内的赋值不会影响外部变量。 - HttpClient滥用:每次调用创建新的
HttpClient实例,容易造成系统套接字资源耗尽。
修正后的代码
1. 核心逻辑调整
保持你的Coin和Root类不变,修改反序列化目标类型,并重构异步调用逻辑:
static async Task Main(string[] args) { Root coinData = await CallApi(); // 示例:遍历输出获取到的币价数据 foreach (var coin in coinData.coins) { Console.WriteLine($"{coin.name}: ${coin.price}"); } Console.ReadKey(); } private static async Task<Root> CallApi() { using var httpClient = new HttpClient(); string url = "https://api.coinstats.app/public/v1/coins?skip=0&limit=50¤cy=USD"; var httpResponse = await httpClient.GetAsync(url); // 确保请求成功,否则抛出异常 httpResponse.EnsureSuccessStatusCode(); string jsonResponse = await httpResponse.Content.ReadAsStringAsync(); // 反序列化为单个Root对象,而非List<Root> return JsonConvert.DeserializeObject<Root>(jsonResponse); }
2. 可选:实体类规范优化(符合C#编码习惯)
不影响功能,但建议将属性名改为PascalCase,并通过特性映射JSON的驼峰命名:
public class Coin { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("icon")] public string Icon { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("symbol")] public string Symbol { get; set; } [JsonProperty("rank")] public int Rank { get; set; } [JsonProperty("price")] public double Price { get; set; } // 其余属性按同样方式修改 } public class Root { [JsonProperty("coins")] public List<Coin> Coins { get; set; } }
关键说明
- 类型匹配验证:可以直接访问API URL查看返回结构,确认顶层是单个对象而非数组,因此必须反序列化为
Root类型。 - 异步方法规范:将
async void改为async Task<Root>,外部通过await等待操作完成并直接获取结果,避免参数传递的引用问题。 - HttpClient资源管理:用
using语句管理实例生命周期,或者创建静态实例复用,避免频繁创建销毁导致的资源泄漏。
内容的提问来源于stack exchange,提问作者vajuakos
相关产品推荐
相关产品推荐

