Spring Boot Redis缓存反序列化异常问题求助
嘿,我之前也踩过Redis缓存JSON反序列化的坑,结合你的场景来看,「Could not read JSON」这个报错大概率是这几个原因导致的,咱们一步步来排查解决:
可能的原因及解决方案
1. MyObject类缺少序列化相关配置
Redis缓存对象时,不管是序列化还是反序列化,都需要类满足相应的规范:
- 必须实现
Serializable接口(如果用JDK序列化的话),或者确保Jackson能识别类的结构 - 要有无参构造函数(Jackson反序列化的必要条件)
- 所有需要序列化的字段都要有对应的getter/setter方法
给你个示例代码参考:
import java.io.Serializable; public class MyObject implements Serializable { // 建议显式声明序列化ID,避免类结构变化导致反序列化失败 private static final long serialVersionUID = 1L; private Integer id; private String name; // 其他字段... // 必须的无参构造函数 public MyObject() {} // 所有字段的getter和setter public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
如果有一些字段不需要序列化,或者反序列化时遇到未知字段,可以加@JsonIgnoreProperties(ignoreUnknown = true)注解在类上。
2. Redis缓存的序列化方式不匹配
默认的Redis序列化器可能用的是JdkSerializationRedisSerializer,而你接口返回的是JSON格式,这就会导致序列化和反序列化的格式不兼容,直接报错。
你需要配置RedisTemplate或者CacheManager,指定用Jackson2JsonRedisSerializer来处理对象的序列化:
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @EnableCaching public class RedisCacheConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 配置Jackson序列化器 Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); // 设置key和value的序列化器 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class))); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) .build(); } }
3. 缓存的旧数据与当前类结构不匹配
如果之前Redis里已经缓存了旧版本的MyObject数据(比如字段名修改、字段类型变更),现在反序列化时就会因为结构不匹配报错。
解决方法很简单:
- 直接清理Redis中对应缓存key的数据(比如用
DEL data:1命令删除key) - 后续给缓存key加上版本号,比如
myObject:v1:1,避免新旧数据冲突
4. 缓存注解的使用问题
如果你的Service层用了@Cacheable注解,要确保注解配置和返回值类型一致:
import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class MyService { @Autowired private MyRepository repository; // 确保key的表达式正确,返回值是MyObject类型 @Cacheable(value = "myObjectCache", key = "#id") public MyObject findOneById(String id) { return repository.findById(Integer.parseInt(id)).orElse(null); } }
注意不要返回null或者其他类型的对象,否则反序列化也会出问题。
如果以上方法都没解决,建议把完整的错误堆栈信息贴出来,能更精准定位问题~
内容的提问来源于stack exchange,提问作者Heril Muratovic
相关产品推荐
相关产品推荐

