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

如何避免自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:25:04