java中redis缓存多态对象json序列化类型丢失,根源是jackson默认不写入运行时类型信息;需启用defaulttyping并配置objectmapper,配合typereference或convertvalue精准反序列化。

Java中多态对象在Redis缓存中序列化为JSON时类型丢失,本质是Jackson默认不写入运行时类型信息,反序列化时只能还原成LinkedHashMap或基础包装类,无法恢复原始子类。解决的关键在于让JSON带上可识别的类型标记,并确保反序列化时能准确还原。
启用Jackson的类型识别机制
这是最直接有效的方案。通过ObjectMapper开启默认类型信息,使序列化输出包含@class字段:
- 配置示例:
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); - 效果:User子类
AdminUser序列化后变成{"@class":"com.example.AdminUser","name":"张三","role":"admin"} - 注意:仅对非final类生效;若用
GenericJackson2JsonRedisSerializer,需传入已配置好的ObjectMapper
避免泛型擦除导致的集合元素类型丢失
泛型如List<user></user>在反序列化时,仅靠JSON字符串无法推断元素类型,Jackson会默认用LinkedHashMap填充列表:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 正确做法:使用
TypeReference显式指定完整类型mapper.readValue(json, new TypeReference<list>>() {})</list> - 在RedisTemplate中,不建议直接
get(key)强转,而应先取String再用ObjectMapper按需反序列化 - 若用Spring Cache,可在
@Cacheable方法返回值上标注具体泛型类型(部分版本支持),或改用CacheResolver配合自定义反序列逻辑
兼容性与生产环境权衡
带@class的JSON虽能解决问题,但引入额外字段,影响跨服务协作和人工可读性:
- 推荐策略:内部服务统一使用该配置;对外提供缓存数据时,改用DTO+明确类型字段(如
"type": "admin")替代@class - 替代方案:用
convertValue二次转换——先取Object,再用mapper.convertValue(obj, TargetClass.class),性能略低但更可控 - 极端情况(如空集合):避免用
List.of(),改用Collections.emptyList(),前者序列化后无类型标识,后者会保留["java.util.Collections$EmptyList",[]]
检查序列化器是否覆盖了类型配置
常见陷阱是RedisTemplate配置了多个序列化器,或不同Bean间ObjectMapper实例未共享配置:
- 确认
GenericJackson2JsonRedisSerializer构造时传入的是已调用activateDefaultTyping的ObjectMapper - 避免在配置类中重复new ObjectMapper(),应定义为
@Bean并复用 - 若使用
Jackson2JsonRedisSerializer,必须显式调用setObjectMapper,否则默认不启用类型识别
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










