ASP.NET Core 3.1中如何编写仅自定义Read方法的System.Text.Json转换器?
解决System.Text.Json自定义转换器仅自定义反序列化的问题
你遇到的问题是因为在Write方法中直接调用JsonSerializer.Serialize时,会再次使用你注册的自定义转换器,导致序列化逻辑异常,最终输出了字符串形式的JSON对象而非正常的JSON结构。下面提供两种可行的解决方案:
方法一:在Write方法中使用移除当前转换器的新配置
修改你的Write方法,创建一个复制原有配置但移除当前自定义转换器的JsonSerializerOptions实例,再用这个新配置进行序列化,就能触发默认的序列化逻辑:
public class MyTypeConverter<T> : JsonConverter<T> where T : MyType<T> { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 执行你的自定义反序列化逻辑 // 示例:假设MyType<T>有Key和Value属性,自定义读取逻辑 using (var doc = JsonDocument.ParseValue(ref reader)) { var root = doc.RootElement; var key = root.GetProperty("Key").GetInt32(); var value = root.GetProperty("Value").GetString(); // 假设MyType<T>有对应的构造函数 return (T)Activator.CreateInstance(typeof(T), key, value); } } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // 创建新配置,复制原有设置并移除当前转换器 var defaultOptions = new JsonSerializerOptions(options); defaultOptions.Converters.Remove(this); // 使用默认配置序列化,输出正常的JSON对象 JsonSerializer.Serialize(writer, value, defaultOptions); } }
方法二:使用JsonConverterFactory支持所有MyType泛型类型(可选)
如果你需要让所有MyType<T>的泛型实例都自动应用这个转换器,可以创建一个JsonConverterFactory来批量处理,避免手动注册每个具体的泛型类型:
public class MyTypeConverterFactory : JsonConverterFactory { public override bool CanConvert(Type typeToConvert) { // 判断当前类型是否是MyType<>的泛型实例 return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(MyType<>); } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { // 获取泛型参数T Type genericArg = typeToConvert.GetGenericArguments()[0]; // 创建对应的MyTypeConverter<T>实例 Type converterType = typeof(MyTypeConverter<>).MakeGenericType(genericArg); return (JsonConverter)Activator.CreateInstance(converterType); } }
然后在Startup.cs中注册这个工厂:
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new MyTypeConverterFactory()); });
注意事项
- 你原来代码里
Write方法的参数TEnum是笔误,要改成T才能匹配泛型转换器的类型。 - 复制
JsonSerializerOptions是浅复制,对于大部分常规配置场景已经足够;如果你的配置中有复杂自定义转换器或特殊设置,需要确保复制逻辑能覆盖你的需求。
内容的提问来源于stack exchange,提问作者Dabbas
相关产品推荐
相关产品推荐

