C#中JsonConvert.DeserializeObject设NullValueHandling.Ignore仍报空值异常如何解决
问题成因
NullValueHandling.Ignore未生效的核心原因是逻辑触发顺序问题:该配置的作用是反序列化时如果JSON字段为null,就跳过给类属性赋值、使用类初始化后的默认值。但你的hitpoints等字段定义为不可空值类型int,JSON中该字段为null时,Newtonsoft.Json首先要完成null到int的类型转换,转换失败异常会先触发,还没走到NullValueHandling的判断逻辑。- 自定义带参构造函数放大了该问题:你的Entry类仅定义了带参构造函数,反序列化时Newtonsoft.Json会优先使用这个构造函数初始化对象,需要将JSON字段值直接映射为构造函数的入参,入参
hitpoints_p是不可空int类型,传入null时直接触发转换异常,属性上声明的NullValueHandling特性对构造函数入参不生效。 - 额外注意:你贴出的Entry类代码末尾有多余的
[JsonProperty]特性,属于语法冗余,虽不是直接报错原因,但会导致编译警告。
解决方案
按实现成本从低到高排序,任选其一即可:
- 修改为可空值类型(最简便)
把hitpoints、items、current等可能为null的值类型属性改为对应的可空类型int?、bool?,null可以正常接收赋值,业务使用时可通过hitpoints ?? 0的方式获取非空默认值。
修改示例:
public int? hitpoints { get; set; } public bool? incomplete { get; set; }
- 添加无参构造函数让NullValueHandling生效
给Entry类新增无参构造函数,反序列化时会优先用无参构造初始化对象,此时属性上的NullValueHandling.Ignore会正常生效,JSON字段为null时跳过赋值,自动使用值类型的默认值(int默认0、bool默认false)。
修改示例:
public class Entry { // 新增无参构造函数 public Entry() { } // 原有带参构造函数保留即可 public Entry(int id_p, string name_p, string last_updated_p, bool incomplete_p, bool valid_p, string start_date_p, int items_p, int size_p, int hitpoints_p) { // 原有逻辑不变 } // 原有属性定义不变 }
- 新增值类型null转换器(无需修改实体类)
如果不能修改现有Entry类的定义,可以在序列化配置中添加自定义转换器,遇到null要赋值给值类型时自动填充默认值:
// 自定义int类型null转换器 public class IntNullConverter : JsonConverter<int> { public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer) { return reader.Value == null ? 0 : Convert.ToInt32(reader.Value); } public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer) { writer.WriteValue(value); } } // 注册到序列化配置中 var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, Converters = { new IntNullConverter() } };
内容的提问来源于stack exchange,提问作者TBowman
相关产品推荐
相关产品推荐

