Newtonsoft反序列化如何实现属性返回空对象而非null
Newtonsoft.Json反序列化null值转空对象实现方案
问题核心
使用Newtonsoft.Json反序列化JSON到C#类实例时,部分引用类型属性在JSON对应值为null时,需要自动初始化为对应类型的空结构实例,而非保留null值。
你之前在PartyIdentification属性上配置的[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]无法生效,原因是:
- 该配置仅在JSON结构中缺失对应字段时触发默认值填充,字段存在但值为
null时不会触发逻辑 DefaultValueAttribute本身不支持传入引用类型实例作为默认值,无法直接配置空对象作为填充目标
推荐方案:自定义通用Null转空对象转换器
该方案侵入性最低、灵活度最高,不需要修改原有类的构造逻辑,可精准控制生效范围,是最优选择。
第一步:实现自定义JsonConverter
public class NullToEmptyObjectConverter : JsonConverter { // 仅处理非值类型、非字符串的引用类型 public override bool CanConvert(Type objectType) { return !objectType.IsValueType && objectType != typeof(string); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 读取到JSON null值时,通过无参构造生成空实例返回 if (reader.TokenType == JsonToken.Null) { // 抽象类、接口等无法实例化的类型兜底返回null,避免运行时报错 if (objectType.IsAbstract || objectType.IsInterface) return null; return Activator.CreateInstance(objectType, nonPublic: true); } // 非null值走默认反序列化逻辑 var instance = Activator.CreateInstance(objectType, nonPublic: true); serializer.Populate(reader, instance); return instance; } // 禁用序列化阶段的自定义逻辑,不影响原有序列化行为 public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
第二步:按需配置生效范围
你可以根据业务需求选择全局生效或者仅指定属性生效:
- 仅指定属性生效(推荐):给需要做null转空对象的属性添加
[JsonConverter]特性,不会影响其他属性的默认反序列化逻辑
public class Party { [JsonConverter(typeof(NullToEmptyObjectConverter))] public PartyIdentification PartyIdentification { get; set; } } public class PartyIdentification { [JsonProperty(PropertyName = "ID")] [JsonConverter(typeof(NullToEmptyObjectConverter))] public PartyIdentificationId Id { get; set; } }
- 全局生效:反序列化时将转换器加入
JsonSerializerSettings,所有匹配CanConvert规则的类型遇到null都会自动生成空实例
var settings = new JsonSerializerSettings { Converters = { new NullToEmptyObjectConverter() } }; var result = JsonConvert.DeserializeObject<SftiOrderResponse>(jsonContent, settings);
轻量替代方案:构造函数初始化+Null值忽略
如果项目嵌套层级少、逻辑固定,也可以直接在类的无参构造函数中初始化嵌套属性,配合null值忽略配置实现需求,不需要额外写转换器。
实现代码
首先给对应类添加无参构造,初始化嵌套属性:
public class Party { public Party() { PartyIdentification = new PartyIdentification(); } // 配置null值忽略:遇到JSON null时不覆盖构造函数初始化的实例 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public PartyIdentification PartyIdentification { get; set; } } public class PartyIdentification { public PartyIdentification() { Id = new PartyIdentificationId(); } [JsonProperty(PropertyName = "ID", NullValueHandling = NullValueHandling.Ignore)] public PartyIdentificationId Id { get; set; } }
注意:必须给属性配置
NullValueHandling.Ignore,否则Newtonsoft默认会在遇到JSON null时,把构造函数里初始化的实例覆盖为null。
方案对比
- 自定义JsonConverter方案:灵活度高,不需要修改原有类定义,可精准控制生效范围,不影响序列化逻辑,适合绝大多数业务场景,为首选方案
- 构造函数初始化方案:代码简单直观,不需要额外编写转换器,但嵌套层级多时需要重复编写构造初始化逻辑,适合结构简单的固定模型
内容的提问来源于stack exchange,提问作者Don Juan
相关产品推荐
相关产品推荐

