ASP.NET Core多态反序列化缺失类型鉴别器时如何获取有效错误信息?
解决多态反序列化缺失类型鉴别器的友好错误问题
可以通过自定义JsonConverter<NotificationWeb>拦截缺失type字段的场景,统一返回和无效类型鉴别器一致的友好错误信息,具体实现如下:
1. 编写自定义转换器
public class NotificationWebConverter : JsonConverter<NotificationWeb> { private readonly JsonConverter<NotificationWeb> _defaultConverter; public NotificationWebConverter(JsonSerializerOptions options) { // 获取框架默认的多态反序列化转换器 _defaultConverter = (JsonConverter<NotificationWeb>)options.GetConverter(typeof(NotificationWeb)); } public override NotificationWeb? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 复制读取器,检查当前对象是否包含"type"字段 var readerCopy = reader; if (readerCopy.TokenType != JsonTokenType.StartObject) { throw new JsonException("无效的通知对象格式"); } bool hasTypeField = false; while (readerCopy.Read()) { if (readerCopy.TokenType == JsonTokenType.PropertyName && readerCopy.GetString() == "type") { hasTypeField = true; break; } // 跳过属性值,继续遍历下一个属性 if (readerCopy.TokenType == JsonTokenType.PropertyName) { readerCopy.Read(); JsonSerializer.Skip(ref readerCopy); } } // 缺失type字段时抛出统一错误 if (!hasTypeField) { throw new JsonException("类型鉴别器无效"); } // 交给默认转换器处理正常的多态反序列化 return _defaultConverter.Read(ref reader, typeToConvert, options); } public override void Write(Utf8JsonWriter writer, NotificationWeb value, JsonSerializerOptions options) { _defaultConverter.Write(writer, value, options); } }
2. 注册转换器
有两种方式可以将自定义转换器接入系统:
方式一:通过特性绑定到抽象类
直接在NotificationWeb上添加JsonConverter特性:
[JsonConverter(typeof(NotificationWebConverter))] [JsonPolymorphic(TypeDiscriminatorPropertyName = "type")] [JsonDerivedType(typeof(EmailNotificationWeb), "Email")] [JsonDerivedType(typeof(SmsNotificationWeb), "Sms")] public abstract record NotificationWeb;
方式二:全局配置(适用于ASP.NET Core)
在项目启动配置中添加转换器到序列化选项:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new NotificationWebConverter(options.JsonSerializerOptions)); });
3. 效果说明
- 当请求数组元素缺失
type字段时,会抛出包含“类型鉴别器无效”的异常,和传入无效type值时的错误提示保持一致; - 正常传入有效
type字段时,依然保留原有多态反序列化逻辑; - 传入无效
type值时,框架默认的“未知类型”错误会继续生效,若需要完全统一错误信息,可在转换器中额外处理未知类型的场景。
内容的提问来源于stack exchange,提问作者Ilya Chernomordik
相关产品推荐
相关产品推荐

