使用C# GetFromJsonAsync反序列化JSON时无法获取子对象值
问题描述
使用C#的GetFromJsonAsync方法反序列化Open Meteo API返回的JSON时,能正常提取latitude、longitude等顶层字段,但无法获取current_weather子结构中的temperature、windspeed等值,当前代码中Temperature始终返回0,尝试创建current_weather对应的类但未成功。
示例JSON响应:
{ "latitude": 38.4375, "longitude": 27.25, "generationtime_ms": 0.21195411682128906, "utc_offset_seconds": 0, "timezone": "GMT", "timezone_abbreviation": "GMT", "elevation": 137, "current_weather": { "temperature": 12.3, "windspeed": 6.4, "winddirection": 137, "weathercode": 3, "time": "2023-02-26T06:00" } }
原代码:
using System.Net.Http.Json; using System.Runtime.ConstrainedExecution; namespace HttpClientExtensionMethods { public class City { public float Latitude { get; set; } public float Longitude { get; set; } public float Temperature { get; set; } } public class Program { public static async Task Main() { using HttpClient client = new() { BaseAddress = new Uri("https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true") }; // Get Json Weather information. City? city = await client.GetFromJsonAsync<City>(""); Console.WriteLine($"Latitude: {city?.Latitude}"); Console.WriteLine($"Longitude: {city?.Longitude}"); Console.WriteLine($"Temperature: {city?.Temperature}"); } } }
解决方案
核心问题是类结构未与JSON的嵌套层级匹配:原City类中的Temperature属性尝试映射顶层字段,但JSON中temperature属于current_weather子对象,因此无法匹配,最终返回float类型的默认值0。
需要按以下步骤修改:
定义
CurrentWeather类,对应JSON中的current_weather子结构:
由于JSON使用蛇形命名,C#中建议用帕斯卡命名并通过JsonPropertyName特性映射到JSON键名,确保序列化/反序列化正确匹配。修改
City类,添加CurrentWeather类型的属性,同样用特性映射JSON键名。更新输出逻辑,访问嵌套对象中的属性值。
修改后的完整代码:
using System.Net.Http.Json; using System.Text.Json.Serialization; namespace HttpClientExtensionMethods { public class City { [JsonPropertyName("latitude")] public float Latitude { get; set; } [JsonPropertyName("longitude")] public float Longitude { get; set; } [JsonPropertyName("current_weather")] public CurrentWeather? CurrentWeather { get; set; } } public class CurrentWeather { [JsonPropertyName("temperature")] public float Temperature { get; set; } [JsonPropertyName("windspeed")] public float WindSpeed { get; set; } [JsonPropertyName("winddirection")] public int WindDirection { get; set; } [JsonPropertyName("weathercode")] public int WeatherCode { get; set; } [JsonPropertyName("time")] public DateTime Time { get; set; } } public class Program { public static async Task Main() { using HttpClient client = new() { BaseAddress = new Uri("https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true") }; City? city = await client.GetFromJsonAsync<City>(""); Console.WriteLine($"Latitude: {city?.Latitude}"); Console.WriteLine($"Longitude: {city?.Longitude}"); Console.WriteLine($"Temperature: {city?.CurrentWeather?.Temperature}"); Console.WriteLine($"Wind Speed: {city?.CurrentWeather?.WindSpeed}"); } } }
关键说明
- 使用
JsonPropertyName特性确保C#类属性与JSON键名严格匹配,避免因命名风格差异导致映射失败。 - 嵌套对象属性需声明为可空类型(如
CurrentWeather?),防止JSON中该字段缺失时引发空引用异常。 - 若不需要所有子字段,可只保留
CurrentWeather类中需要的属性(如仅Temperature),反序列化时会自动忽略未定义的字段。
内容的提问来源于stack exchange,提问作者PairMem
相关产品推荐
相关产品推荐

