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

如何自动反序列化.NET中双重序列化的JSON属性值?

解决方案:通过泛型转换器工厂实现自动反序列化

你可以通过自定义JsonConverterFactory+泛型转换器的方式,利用System.Text.Json的高层API解决这个问题,无需修改控制器代码,也不用直接操作底层的Utf8JsonReader令牌。

实现步骤

1. 编写泛型转换器工厂

这个工厂会自动识别所有Foo<T>类型,并为每个具体的Foo<T>创建对应的转换器:

public class FooConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
    {
        // 判断当前类型是否为Foo<T>的泛型实例
        return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Foo<>);
    }

    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
    {
        // 获取泛型参数T的类型
        Type genericType = typeToConvert.GetGenericArguments()[0];
        // 动态创建对应的FooConverter<T>实例
        Type converterType = typeof(FooConverter<>).MakeGenericType(genericType);
        return (JsonConverter)Activator.CreateInstance(converterType, options);
    }

    // 针对具体Foo<T>的转换器实现
    private class FooConverter<T> : JsonConverter<Foo<T>>
    {
        private readonly JsonSerializerOptions _serializerOptions;

        public FooConverter(JsonSerializerOptions options)
        {
            // 复制传入的配置,避免修改全局配置,同时移除自身转换器防止递归
            _serializerOptions = new JsonSerializerOptions(options);
            _serializerOptions.Converters.RemoveAll(c => c.GetType() == typeof(FooConverter<T>));
        }

        public override Foo<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            // 第一步:用高层API把请求JSON反序列化为Foo<string>
            var stringWrapper = JsonSerializer.Deserialize<Foo<string>>(ref reader, _serializerOptions);
            if (stringWrapper == null) return null;

            // 第二步:把内嵌的JSON字符串反序列化为目标类型T
            T targetData = JsonSerializer.Deserialize<T>(stringWrapper.data, _serializerOptions);
            return new Foo<T> { data = targetData };
        }

        public override void Write(Utf8JsonWriter writer, Foo<T> value, JsonSerializerOptions options)
        {
            // 可选:如果需要把Foo<T>序列化为双重JSON格式,实现反向逻辑
            var stringWrapper = new Foo<string>
            {
                data = JsonSerializer.Serialize(value.data, _serializerOptions)
            };
            JsonSerializer.Serialize(writer, stringWrapper, _serializerOptions);
        }
    }
}

2. 注册转换器到ASP.NET Core

在Program.cs(或Startup.cs)中全局注册这个转换器工厂,控制器会自动使用它处理所有Foo<T>类型的参数绑定:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new FooConverterFactory());
    });

方案说明

  • 无需修改控制器:所有转换逻辑在全局转换器中完成,控制器代码保持原样即可
  • 利用高层API:全程使用JsonSerializer.Deserialize/Serialize等高层方法,避免直接操作底层令牌的复杂逻辑
  • 自动适配所有泛型实例:转换器工厂会自动识别Foo<SomeComplexClass>、Foo<OtherMoreDifferentClass>等所有Foo<T>类型,无需为每个T单独编写转换器

以你提供的例子为例,当收到{"data":"{\"Foo\":\"hello\"}"}时:

  1. 转换器先将其反序列化为Foo<string>,其中data值为"{\"Foo\":\"hello\"}"
  2. 再将该字符串反序列化为SomeComplexClass类型
  3. 最终控制器收到的myFoo.data就是SomeComplexClass实例,符合预期

内容的提问来源于stack exchange,提问作者Brandon Piña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:50:24