C#中如何在查询JSON JToken字段前判断其是否存在?
处理JSON可选字段的空值判断问题
你的程序崩溃的核心原因是:当total字段不存在时,result.SelectTokens("results.main[*].item.total")会返回空序列,此时调用First()会直接抛出InvalidOperationException——First()要求序列至少有一个元素,空序列会触发异常,你的空值判断根本没机会执行。
下面是几种可行的解决方法:
方法1:改用FirstOrDefault()替代First()
这是最直接的修改,FirstOrDefault()在序列为空时会返回null而非抛出异常,之后再做空值判断即可:
if (count > 0) { var totalToken = result.SelectTokens("results.main[*].item.total").FirstOrDefault(); var total = totalToken != null ? totalToken.ToString() : string.Empty; }
方法2:先检查字段是否存在再取值
如果需要更精细的控制,可以遍历每个item节点,先判断total字段是否存在:
if (result.HasValues) { foreach (var itemToken in result.SelectTokens("results.main[*].item")) { if (itemToken is JObject itemObj) { // 直接判断字段是否存在 if (itemObj.ContainsKey("total")) { var total = itemObj["total"].ToString(); // 处理total值 } else { // 字段不存在时的逻辑 } } } }
方法3:使用强类型模型(推荐)
定义与JSON结构匹配的类,利用Json.NET的特性自动处理可选字段,这种方式类型更安全,代码可读性更高:
// 定义模型类 public class ResultRoot { [JsonProperty("results")] public Results Results { get; set; } } public class Results { [JsonProperty("copyright")] public string Copyright { get; set; } [JsonProperty("main")] public List<MainEntry> Main { get; set; } } public class MainEntry { [JsonProperty("item")] public ItemData Item { get; set; } } public class ItemData { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("date")] public string Date { get; set; } // 可选字段用可空类型,不存在时自动为null [JsonProperty("total")] public long? Total { get; set; } }
然后修改反序列化和取值逻辑:
// 改用异步await避免死锁(原代码的.Result可能导致死锁) var response = await httpClient.GetAsync("getData.json?thing=abc"); response.EnsureSuccessStatusCode(); var jsonContent = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<ResultRoot>(jsonContent); if (result?.Results?.Main != null && result.Results.Main.Count > 0) { var firstItem = result.Results.Main[0].Item; var total = firstItem.Total.HasValue ? firstItem.Total.ToString() : string.Empty; }
额外提示:原代码中使用.Result同步等待异步操作,容易在某些上下文(比如UI线程)导致死锁,建议改用await异步处理。
内容的提问来源于stack exchange,提问作者eek
相关产品推荐
相关产品推荐

