JSON.Net处理不存在的JSON令牌:如何返回默认值而非抛出异常
处理JSON.Net中不存在的令牌(返回默认值而非抛出异常)
我之前对接Path of Exile的公共藏身处API时,也遇到过一模一样的问题——物品的可选字段太多,稍不注意就会因为令牌不存在抛出异常。下面是几种实用的解决方法,按使用场景分:
1. 使用JSON.Linq时的安全查询(最直接适配你的场景)
当你用JObject/JToken做LINQ查询时,不要直接用["key"]访问后立刻Value<T>(),而是用以下两种安全方式:
方式A:SelectToken + 空传播 + 空合并
SelectToken会在找不到对应令牌时返回null,结合空传播运算符?.和空合并??可以轻松返回默认值:
// 假设item是JObject类型的单个物品对象 var abyssJewelValue = item.SelectToken("abyssJewel")?.Value<string>() ?? "默认值"; // 如果是数值类型(比如int) var stackSize = item.SelectToken("stackSize")?.Value<int>() ?? 0;
方式B:TryGetValue方法
如果需要更明确的逻辑分支,可以用TryGetValue判断令牌是否存在:
// C# 7+ 简洁写法 if (item.TryGetValue("abyssJewel", out JToken? token)) { var abyssJewelValue = token.Value<string>(); // 处理有值的情况 } else { var abyssJewelValue = "默认值"; // 或对应类型的默认值,比如null、0 // 处理无值的情况 }
2. 强类型反序列化(更易维护的长期方案)
如果你的项目需要频繁处理这些数据,建议定义对应的实体类,通过JSON.Net的特性自动处理默认值:
步骤1:定义实体类
给可选属性设置默认值,并配置JsonProperty的默认值处理规则:
public class PoeItem { // 必填字段直接定义 public string Name { get; set; } = string.Empty; // 可选字段:配置自动填充默认值 [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public string AbyssJewel { get; set; } = "默认值"; // 数值类型同理 [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public int StackSize { get; set; } = 0; }
步骤2:反序列化
直接将API返回的JSON反序列化到实体类,不存在的字段会自动填充你设置的默认值:
var responseJson = await httpClient.GetStringAsync("http://www.pathofexile.com/api/public-stash-tabs"); var stashResponse = JsonConvert.DeserializeObject<PoeStashResponse>(responseJson); // 此时stashResponse中的Items列表里,没有AbyssJewel属性的物品会自动使用"默认值"
3. 使用动态对象(快速原型开发)
如果只是临时测试或快速验证逻辑,可以用dynamic类型,但注意这种方式没有编译时检查:
dynamic item = JsonConvert.DeserializeObject<dynamic>(itemJson); var abyssJewelValue = item.abyssJewel ?? "默认值";
这些方法都能完美解决POE API中可选字段的问题,我个人更推荐强类型反序列化的方案,长期维护起来更省心;而LINQ查询的方式适合临时的局部处理场景。
内容的提问来源于stack exchange,提问作者XomRng
相关产品推荐
相关产品推荐

