You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:20:32