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

.NET 8中使用System.Text.Json将null序列化为空对象{}的问题

System.Text.Json将null属性序列化为空对象的解决方案

问题背景

使用环境:
-.NET 8
-System.Text.Json 序列化器

定义类:

public class SampleClass
{
    public SampleClassDetail? FirstProperty { get; set; }
    public SampleClassDetail? SecondProperty { get; set; }
}

public class SampleClassDetail
{
    public int MyProperty { get; set; }
}

创建实例:

SampleClass sample = new()
{
    FirstProperty = new SampleClassDetail { MyProperty = 1 }
};

默认序列化结果:

{
  "FirstProperty": {
    "MyProperty": 1
  },
  "SecondProperty": null
}

期望将SecondProperty的null转为{},但自定义转换器未生效:

public class SampleClassDetailConverter : JsonConverter<SampleClassDetail?>
{
    public override SampleClassDetail? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, SampleClassDetail? value, JsonSerializerOptions options)
    {
        if (value == null)
        {
            writer.WriteStartObject();
            writer.WriteEndObject();
        }
        else
        {
            var newOptions = new JsonSerializerOptions(options);
            newOptions.Converters.Remove(this);
            JsonSerializer.Serialize(writer, value, newOptions);
        }
    }
}

var options = new JsonSerializerOptions();
options.Converters.Add(new SampleClassDetailConverter());

string serialized = JsonSerializer.Serialize(sample, options);

问题原因

自定义转换器未生效的核心原因是:JsonConverter的HandleNull属性默认值为false,当属性值为null时,System.Text.Json不会调用转换器的Write方法,而是直接输出null值。

解决方案

修改自定义转换器,重写HandleNull属性并返回true,确保null值也会经过转换器处理:

public class SampleClassDetailConverter : JsonConverter<SampleClassDetail?>
{
    // 重写HandleNull,让转换器处理null值
    public override bool HandleNull => true;

    public override SampleClassDetail? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, SampleClassDetail? value, JsonSerializerOptions options)
    {
        if (value == null)
        {
            writer.WriteStartObject();
            writer.WriteEndObject();
        }
        else
        {
            var newOptions = new JsonSerializerOptions(options);
            newOptions.Converters.Remove(this);
            JsonSerializer.Serialize(writer, value, newOptions);
        }
    }
}

修改后重新序列化,即可得到期望结果:

{
  "FirstProperty": {
    "MyProperty": 1
  },
  "SecondProperty": {}
}

补充说明

如果需要同时处理反序列化逻辑,可实现Read方法,确保从空对象反序列化为null或默认实例:

public override SampleClassDetail? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    if (reader.TokenType == JsonTokenType.StartObject)
    {
        // 读取空对象
        reader.Read();
        if (reader.TokenType == JsonTokenType.EndObject)
        {
            return null; // 或返回 new SampleClassDetail()
        }
        // 如果对象有属性,正常反序列化
        var newOptions = new JsonSerializerOptions(options);
        newOptions.Converters.Remove(this);
        return JsonSerializer.Deserialize<SampleClassDetail>(ref reader, newOptions);
    }
    return null;
}

内容的提问来源于stack exchange,提问作者blfuentes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:13:14