.NET中如何将对象默认值序列化为null?自定义JSON转换器实现
.NET 序列化时将默认值转为null的实现方案
问题背景
现有以下嵌套C# record类型:
public record Options { public BatterySettings BatterySettings { get; init; } = new(); public LogSettings LogSettings { get; init; } = new(); } public record LogSettings { public string SourceName { get; init; } = "Default"; } public record BatterySettings { public int BatteryLevel { get; init; } = 5; public string BatteryHealth { get; init; } = "Normal"; public BatteryLocations BatteryLocation { get; init; } = BatteryLocations.North; } public enum BatteryLocations { North, South }
初始化对象时仅设置部分属性:
var opt = new Options { BatterySettings = new BatterySettings { BatteryLevel = 10, BatteryHealth = "Low" } }
期望序列化后的JSON中,所有未修改的默认值都转为null,结果如下:
{ "BatterySettings":{ "BatteryLevel":10, "BatteryHealth":"Low", "BatteryLocation":null }, "LogSettings":{ "SourceName":null } }
由于所有属性都有非null的默认值,.NET内置的JSON序列化配置无法直接实现此需求,需要自定义处理逻辑。
解决方案
.NET没有直接的内置配置能实现这个需求,我们可以通过自定义JSON转换器,对比每个属性的当前值与类型默认实例的属性值,将相等的默认值序列化为null。
1. 实现通用默认值转null转换器
using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; public class DefaultValueToNullConverter<T> : JsonConverter<T> where T : new() { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 反序列化逻辑按需实现,此处仅处理序列化 return JsonSerializer.Deserialize<T>(ref reader, options)!; } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { var defaultInstance = new T(); writer.WriteStartObject(); // 遍历类型的所有公开实例属性 foreach (var property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)) { var currentValue = property.GetValue(value); var defaultValue = property.GetValue(defaultInstance); writer.WritePropertyName(property.Name); // 对比值:相等则输出null,否则序列化当前值 if (Equals(currentValue, defaultValue)) { writer.WriteNullValue(); } else { JsonSerializer.Serialize(writer, currentValue, property.PropertyType, options); } } writer.WriteEndObject(); } }
2. 配置序列化选项并使用转换器
给需要处理的每个record类型添加转换器,然后执行序列化:
var serializeOptions = new JsonSerializerOptions { Converters = { new DefaultValueToNullConverter<Options>(), new DefaultValueToNullConverter<BatterySettings>(), new DefaultValueToNullConverter<LogSettings>() }, WriteIndented = true // 格式化输出,可选 }; var jsonResult = JsonSerializer.Serialize(opt, serializeOptions);
关键说明
- 转换器采用泛型设计,只要类型有公开无参构造函数(如示例中的record)就能复用
- 枚举类型可以直接通过
Equals对比值,无需额外处理 - 若有更深层次的嵌套类型,只需给对应类型添加转换器即可
- 反序列化逻辑可根据需求调整,比如将JSON中的
null转回类型的默认值
内容的提问来源于stack exchange,提问作者K. Vu
相关产品推荐
相关产品推荐

