反序列化自定义异常失败源于jackson无法识别json中的类型信息,应通过白名单策略的polymorphictypevalidator、异常类上@jsontypeinfo注解、统一objectmapper配置及避免@class硬编码来安全精准解决。

反序列化自定义异常对象失败,本质是 Jackson 无法识别 JSON 中的类型信息,导致把本该还原为 BusinessException 或 ValidationException 的数据,错当成 LinkedHashMap 处理。关键不是“加个注解就完事”,而是让序列化时写入可识别的类型标识,且反序列化时能安全、准确地还原。
启用 DefaultTyping 并限定可信类型范围
直接开启全局多态类型支持(如 activateDefaultTyping(ptv, NON_FINAL))风险高,尤其对异常类这类敏感类型。应显式构建白名单策略:
- 使用
BasicPolymorphicTypeValidator.builder(),只允许你项目中定义的异常类及其父类(如RuntimeException、Exception)参与类型解析 - 禁止通过
@class动态加载任意类,避免反序列化攻击 - 示例配置片段:
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()<br> .allowIfSubType("com.yourpackage.exception")<br> .allowIfSubType(RuntimeException.class)<br> .build();
为异常类显式添加 @JsonTypeInfo 注解
比全局配置更精准、更可控。在自定义异常类上直接声明类型识别规则:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 用
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "@exception"),让序列化后 JSON 带"@exception": "com.yourpackage.exception.BusinessException" - 配合
@JsonSubTypes预定义常见子类,提升反序列化效率与确定性 - 确保所有业务异常都继承统一基类,并在该基类上标注,避免每个类重复配置
Redis 序列化器必须匹配 Jackson 的类型策略
Spring Data Redis 的 Jackson2JsonRedisSerializer 或 GenericJackson2JsonRedisSerializer 必须使用同一套 ObjectMapper 实例,且该实例已配置好上述 PolymorphicTypeValidator 和可见性规则:
- 不要混用多个 ObjectMapper:一个用于 Web 接口(可能禁用类型信息),一个用于 Redis(需启用),极易出错
- 禁用
FAIL_ON_UNKNOWN_PROPERTIES,防止因字段增减导致反序列化中断 - 设置
DEFAULT_MAPPER为单例 Bean,供RedisTemplate和缓存管理器共用
避免 @class 字段残留引发兼容问题
如果历史缓存中已有带旧包名的 @class,而你已迁移异常类位置,反序列化会直接失败:
- 上线前清空相关缓存 key,或加一层兼容逻辑:捕获
InvalidTypeIdException后尝试按新包名 fallback 解析 - 长期方案是改用
Id.NAME+@JsonTypeName,用逻辑名代替全限定名,彻底解耦类路径 - 例如:
@JsonTypeName("biz_error")比@class: "com.old.pkg.BusinessException"更稳定
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










