C# Blazor服务端如何正确反序列化指定结构JSON数组
C# Blazor服务端反序列化JSON数组空引用问题
问题描述
我在服务端C# Blazor项目中尝试反序列化如下JSON数组:
[ { "buy": { "forQuery": { "bid": true, "types": [ 16265 ], "regions": [ 10000002 ], "systems": [ 30000142 ], "hours": 24, "minq": 1 }, "volume": 12177, "wavg": 118125.12, "avg": 118260.00, "variance": 58000.00, "stdDev": 240.83, "median": 118100.00, "fivePercent": 118466.60, "max": 118600.00, "min": 118000.00, "highToLow": true, "generated": 1655337615423 }, "sell": { "forQuery": { "bid": false, "types": [ 16265 ], "regions": [ 10000002 ], "systems": [ 30000142 ], "hours": 24, "minq": 1 }, "volume": 935, "wavg": 178386.31, "avg": 194183.33, "variance": 3731725666.67, "stdDev": 61087.85, "median": 140350.00, "fivePercent": 134900.00, "max": 250000.00, "min": 134900.00, "highToLow": false, "generated": 1655337615423 } } ]
源API地址:EVE Marketer市场数据接口
我只需要提取以下字段:
buy节点下的min、max值sell节点下的min、max值
目前已定义映射类如下:
public class BuySellStat { public double max; public double min; } public class EveMarketerResponse { public BuySellStat Buy; public BuySellStat Sell; }
尝试过反序列化为Dictionary、List、Array等多种类型,始终反序列化失败。
问题复现
失败场景
使用HttpClient.GetFromJsonAsync反序列化时,遍历结果抛出NullReferenceException:
var list = HttpClient.GetFromJsonAsync<List<EveMarketerResponse>>("https://api.evemarketer.com/ec/marketstat/json?typeid=16265&usesystem=30000142").Result; await JsConsoleLogger.LogAsync(list.Count.ToString()); // 浏览器控制台可正常输出list长度 foreach (var response in list) { await JsConsoleLogger.LogAsync(response.Buy.min.ToString()); // 此处抛出空引用异常 await JsConsoleLogger.LogAsync(response.Buy.max.ToString()); await JsConsoleLogger.LogAsync(response.Sell.min.ToString()); await JsConsoleLogger.LogAsync(response.Sell.min.ToString()); }
改用await异步调用GetFromJsonAsync仍然出现相同问题。
正常运行场景
先获取字符串再用Newtonsoft.Json反序列化可以正常运行:
var responseJson = await HttpClient.GetStringAsync("https://api.evemarketer.com/ec/marketstat/json?typeid=16265&usesystem=30000142"); var responseList = JsonConvert.DeserializeObject<List<EveMarketerResponse>>(responseJson); foreach (var response in responseList) { await JsConsoleLogger.LogAsync("buy min" + response.Buy.min.ToString()); await JsConsoleLogger.LogAsync("buy max" + response.Buy.max.ToString()); await JsConsoleLogger.LogAsync("sell min" + response.Sell.min.ToString()); await JsConsoleLogger.LogAsync("sell max" + response.Sell.max.ToString()); }
问题原因
两种反序列化方式表现不一致的核心原因是默认匹配规则不同:
GetFromJsonAsync默认使用System.Text.Json序列化器,该序列化器默认严格区分字段/属性名大小写。接口返回的JSON字段为全小写的buy/sell/min/max,和C#类中定义的大写开头Buy/Sell无法匹配,因此反序列化后Buy、Sell属性为null,访问时抛出空引用异常。JsonConvert.DeserializeObject是Newtonsoft.Json的方法,该序列化器默认不区分大小写匹配字段名,因此可以正常映射。
解决方案
方案1:配置System.Text.Json大小写不敏感(无需修改现有类,推荐)
调用GetFromJsonAsync时传入序列化配置,开启大小写不敏感匹配即可:
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; var list = await HttpClient.GetFromJsonAsync<List<EveMarketerResponse>>( "https://api.evemarketer.com/ec/marketstat/json?typeid=16265&usesystem=30000142", jsonOptions);
如果需要全局生效,可以在Program.cs中配置默认Json序列化选项,避免每次调用重复传参。
方案2:显式指定字段映射关系
给类的成员添加特性,显式声明对应JSON的字段名,不受序列化器默认大小写规则影响:
// 若使用System.Text.Json,引入using System.Text.Json.Serialization; public class BuySellStat { [JsonPropertyName("max")] public double max; [JsonPropertyName("min")] public double min; } public class EveMarketerResponse { [JsonPropertyName("buy")] public BuySellStat Buy; [JsonPropertyName("sell")] public BuySellStat Sell; }
如果使用Newtonsoft.Json,将
[JsonPropertyName]替换为[JsonProperty]特性即可。
内容的提问来源于stack exchange,提问作者soomon
相关产品推荐
相关产品推荐

