.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
相关产品推荐
相关产品推荐

