如何自动反序列化.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\"}"}时:
- 转换器先将其反序列化为
Foo<string>,其中data值为"{\"Foo\":\"hello\"}" - 再将该字符串反序列化为
SomeComplexClass类型 - 最终控制器收到的
myFoo.data就是SomeComplexClass实例,符合预期
内容的提问来源于stack exchange,提问作者Brandon Piña
相关产品推荐
相关产品推荐

