C#中JSON响应反序列化失败,所有变量返回0求助
你遇到的这个问题我之前也碰到过几次——明明用了之前跑通的代码,新API反序列化后所有属性都成了默认值0,大概率是JSON结构、字段匹配或者数据类型不兼容导致的。结合你给出的RootObject类,我整理了几个最可能的排查方向和解决办法:
1. 先确认API返回的实际JSON内容
这是最关键的第一步!很多时候我们想当然认为API返回的结构和自己定义的类一致,但实际可能差很多。你可以在UVApiProxy里加几行代码,把API返回的原始JSON打出来看看:
public static async Task<RootObject> UVApiProxy(double lat, double lon) { using var httpClient = new HttpClient(); var url = $"你的API地址?lat={lat}&lon={lon}"; // 替换成实际请求地址 var response = await httpClient.GetAsync(url); var rawJson = await response.Content.ReadAsStringAsync(); Console.WriteLine(rawJson); // 打印原始JSON,或者写入日志 // 后续反序列化代码... }
看完实际的JSON,就能快速判断是字段名不对、结构嵌套,还是类型不匹配。
2. 检查字段名匹配问题
默认的反序列化器(不管是System.Text.Json还是Newtonsoft.Json)对字段名的大小写、命名风格(比如蛇形date_iso vs 驼峰dateIso)是敏感的。如果API返回的字段名和你的属性名不完全一致,就会匹配失败,属性被设为默认值0。
解决办法:给属性加上序列化特性,明确指定对应的JSON字段名。比如用System.Text.Json的话:
public class RootObject { [JsonPropertyName("lat")] // 这里写API实际返回的字段名 public int lat { get; set; } [JsonPropertyName("lon")] public int lon { get; set; } [JsonPropertyName("date_iso")] public DateTime date_iso { get; set; } [JsonPropertyName("date")] public int date { get; set; } [JsonPropertyName("value")] public double value { get; set; } }
要是用的是Newtonsoft.Json,就换成[JsonProperty("lat")]。
3. 数据类型不兼容是重灾区
你把lat和lon定义成了int,但绝大多数地理API返回的是浮点数(比如37.7749),反序列化时无法把double转成int,就会直接设为0。另外date如果是毫秒级时间戳,用int可能会溢出,也会导致默认值。
解决办法:根据实际JSON的类型调整属性类型:
public class RootObject { public double lat { get; set; } // 改为double兼容浮点数 public double lon { get; set; } public DateTime date_iso { get; set; } public long date { get; set; } // 毫秒级时间戳用long更安全 public double value { get; set; } }
4. 反序列化配置没跟上
如果你之前的代码用了特定的反序列化配置(比如忽略大小写、支持蛇形命名),但新代码里没复用,也会出问题。比如System.Text.Json默认是大小写敏感的,你可以开启忽略大小写的配置:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, // 忽略字段名大小写 PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower // 如果API用蛇形命名 }; var rootObj = JsonSerializer.Deserialize<RootObject>(rawJson, options);
5. 警惕API的嵌套结构
很多API会把数据包裹在一层对象里,比如返回的是{"result": {"lat": 123, "lon": 456}},但你的RootObject直接对应顶层字段,这样反序列化时找不到匹配的属性,自然全是0。
解决办法:根据实际结构调整类,比如定义一个包含嵌套数据的根类:
public class ApiResponse { public RootObject result { get; set; } // 这里的字段名要和API返回的一致 } // 反序列化时用这个根类 var apiResponse = JsonSerializer.Deserialize<ApiResponse>(rawJson); return apiResponse.result;
6. 检查API请求是否成功
最后别忘了确认请求有没有成功——如果API返回404、500这类错误状态码,响应内容可能是空或者错误信息,反序列化后自然全是默认值。可以加一行代码确保请求成功:
var response = await httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); // 状态码不是2xx的话直接抛出异常
先从打印原始JSON开始排查,基本上就能找到问题所在啦!
内容的提问来源于stack exchange,提问作者nurlennart

