Spring Boot 3中GenericJackson2JsonRedisSerializer不自动生效,因默认RedisTemplate仍用JdkSerializationRedisSerializer;必须显式配置key/value序列化器,否则存入为乱码二进制,取值返回LinkedHashMap而非原类型。

Spring Boot 3 中直接使用 GenericJackson2JsonRedisSerializer 是可行的,但必须显式配置,否则它不会自动生效;默认的 RedisTemplate 仍会 fallback 到 JdkSerializationRedisSerializer,导致乱码、类型丢失或反序列化失败。
为什么 GenericJackson2JsonRedisSerializer 在 Spring Boot 3 中不自动生效
Spring Boot 3 默认只对 StringRedisTemplate 配置了 StringRedisSerializer,而泛型版的 RedisTemplate 依然使用 JDK 序列化器 —— 这是历史兼容性设计,不是 bug。如果你没手动覆盖 valueSerializer 和 keySerializer,哪怕引入了 Jackson 依赖,存进去的对象也会变成不可读的二进制字节流。
-
GenericJackson2JsonRedisSerializer不带类型信息,反序列化时默认还原为LinkedHashMap - 它不处理
LocalDateTime、BigDecimal等非标准类型,需额外注册模块 - 它和
Jackson2JsonRedisSerializer的关键区别在于:前者支持泛型擦除后的反序列化(靠写入时记录类名),后者必须在构造时指定具体类型
如何正确配置 GenericJackson2JsonRedisSerializer
你需要在配置类中显式创建 RedisTemplate 实例,并设置其 valueSerializer 为 GenericJackson2JsonRedisSerializer,同时确保 key 使用 StringRedisSerializer(避免 key 也变乱码)。
- 必须调用
setKeySerializer(new StringRedisSerializer()),否则 key 也会被 JSON 序列化,导致 scan 失效或命令报错 - 建议搭配
ObjectMapper注册JavaTimeModule,否则LocalDateTime会抛JsonMappingException - 不要复用同一个
ObjectMapper实例给多个序列化器,避免线程安全问题或配置污染
@Bean
public RedisTemplate<string object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<string object> template = new RedisTemplate();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
((GenericJackson2JsonRedisSerializer) template.getValueSerializer()).setObjectMapper(mapper);
template.afterPropertiesSet();
return template;
}</string></string>
容易踩的坑:反序列化时 ClassCastException 或 null 值
最常见现象是取值后得到 LinkedHashMap 而不是你期望的 User 类型,或者反序列化直接返回 null —— 这通常不是配置遗漏,而是使用方式不对。
- 用
redisTemplate.opsForValue().get("key")取出的是Object,必须显式强转,且仅当存入时用了GenericJackson2JsonRedisSerializer才能保类型 - 如果存入用的是
stringRedisTemplate,取出时却用redisTemplate,会因序列化器不匹配导致解析失败 -
GenericJackson2JsonRedisSerializer内部写入 JSON 时会加一个@class字段(如{"@class":"com.example.User","name":"Alice"}),若原始 JSON 来自外部(如 HTTP 请求体),缺少该字段就无法还原类型
替代方案:什么时候该换用 Jackson2JsonRedisSerializer
如果你的操作对象类型固定、已知(比如缓存都是 User 或 Order),Jackson2JsonRedisSerializer 比 GenericJackson2JsonRedisSerializer 更轻量、更安全,也不依赖 @class 字段。
-
Jackson2JsonRedisSerializer构造时指定类型,反序列化严格按该类型执行,无运行时类型推断开销 - 它不写
@class字段,JSON 更干净,适合与前端或其他语言系统交互 - 但无法用于泛型容器(如
List),除非你手动包装成 wrapper 类
真正复杂的地方不在怎么配,而在于你是否清楚:这个序列化器决定的是「谁来解释 value 字节流」——一旦选错,Redis 里存的数据就再也无法按预期还原。别依赖 IDE 控制台显示“看着像 JSON”就认为成功了,务必用 redis-cli + get key 直接验证原始内容。











