You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:04:11