如何避免自定义System.Text.Json转换器出现递归问题?
解决方案
方案1:使用IJsonOnDeserialized接口(.NET 5+推荐)
如果你的项目基于.NET 5或更高版本,直接实现IJsonOnDeserialized接口即可,这是官方提供的反序列化后处理标准方式,完全不需要自定义转换器,从根源避免递归问题:
public class MyClass : IJsonOnDeserialized { public void OnDeserialized() { // 在这里编写反序列化后的处理逻辑 // do stuff } }
使用时直接调用默认反序列化即可,框架会自动在反序列化完成后执行OnDeserialized方法:
var myObj = JsonSerializer.Deserialize<MyClass>(json);
对应序列化的后处理也有IJsonOnSerialized接口,序列化后会自动调用OnSerialized方法。
方案2:在自定义转换器中使用临时选项跳过自身
如果必须保留自定义转换器(比如兼容旧版本.NET,或有其他自定义逻辑),可以通过创建临时的JsonSerializerOptions,移除当前的自定义转换器后再调用默认序列化/反序列化,避免递归:
[JsonConverter(typeof(MyClassFormatter))] public class MyClass { internal void PostSerialisation() { // do stuff } } public class MyClassFormatter : JsonConverter<MyClass> { public override MyClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 复制原选项并移除当前转换器 var defaultOptions = new JsonSerializerOptions(options); var selfConverter = defaultOptions.Converters.FirstOrDefault(c => c.GetType() == typeof(MyClassFormatter)); if (selfConverter != null) { defaultOptions.Converters.Remove(selfConverter); } // 使用默认逻辑反序列化 var result = JsonSerializer.Deserialize<MyClass>(ref reader, defaultOptions); result.PostSerialisation(); return result; } public override void Write(Utf8JsonWriter writer, MyClass value, JsonSerializerOptions options) { // 同样处理序列化逻辑 var defaultOptions = new JsonSerializerOptions(options); var selfConverter = defaultOptions.Converters.FirstOrDefault(c => c.GetType() == typeof(MyClassFormatter)); if (selfConverter != null) { defaultOptions.Converters.Remove(selfConverter); } JsonSerializer.Serialize(writer, value, defaultOptions); } }
注意:复制JsonSerializerOptions会复制所有配置(比如忽略空值、驼峰命名等),保证默认序列化逻辑和原配置一致。
方案3:全局添加转换器而非类特性绑定
移除类上的[JsonConverter]特性,改为在全局JsonSerializerOptions中添加转换器,这样转换器内部可以直接使用不带该转换器的选项调用默认序列化:
// 移除MyClass上的[JsonConverter]特性 public class MyClass { internal void PostSerialisation() { // do stuff } } public class MyClassFormatter : JsonConverter<MyClass> { public override MyClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 直接使用默认反序列化(因为类上没有绑定转换器,不会递归) var result = JsonSerializer.Deserialize<MyClass>(ref reader); result.PostSerialisation(); return result; } public override void Write(Utf8JsonWriter writer, MyClass value, JsonSerializerOptions options) { // 直接使用默认序列化 JsonSerializer.Serialize(writer, value); } }
调用时需要使用添加了转换器的选项:
var options = new JsonSerializerOptions(); options.Converters.Add(new MyClassFormatter()); var myObj = JsonSerializer.Deserialize<MyClass>(json, options);
这种方式适合需要全局统一配置转换器的场景,但需要确保所有序列化/反序列化操作都使用该选项。
内容的提问来源于stack exchange,提问作者user3200739
相关产品推荐
相关产品推荐

