Redis反序列化错误Could not read JSON: Cannot construct instance of `java.util.ArrayList$SubList`

Redis反序列化错误

最近使用Redis做缓存,用着好好的,返现有一个方法的在从Redis获取缓存时报错,无法正常获取到缓存,从报错信息看,是不能发序列化。在这里记录一下解决方法。

直接贴上错误:
Could not read JSON: Cannot construct instance of java.util.ArrayList$SubList(no Creators, like default construct, exist): no default no-arguments constructor found

因为这个序列化的对象较为复杂,嵌套了多个List对象,由于看到错误信息中提示“no Creators,like default contract”等字样,以为是缺少了无参构造函数,就加上lombok的@NoArgsConstructor注解,重新测试还是同样的错误,其实@NoArgsConstructor不是必须加的,因为已经加了@AllArgsConstructor注解了。
于是又仔细看错误信息,“SubList”,罪魁祸首就是这个方法。我们的代码中确实用到了Sublis方法对缓存对象中的ArrayList进行了截取。正因为使用了这个方法,导致缓存对象无法反序列化。
让我们来看看Sublist的源码:

subList方法返回的是一个List,这个List是一个interface,继承自Collection, 而且Collection也是interface,一层层看过去,都是没有实现Serializable接口的,所以不能序列化/反序列化。

到这里大家应该明白了,ArrayList.subList方法返回的对象是一个sublist类型的视图,这个sublist类型的是ArrayList的一个内部类,不支持序列化。视图的含义就是它里面的元素数量变了,但是操作其中的元素实际上还是操作的原来的list,并不是新的那份list。如果改变原有的list,那么就会抛出ConcurrentModificationException异常。

根本原因找到了,就看看怎么解决吧。
解决方法也是挺简单的,重新创建一个实现序列化的List,将截取后的list存入,从而实现可序列化。

// 原错误代码
bannerList = bannerList.subList(0, SLIDING_SIZE);
// 修改后的正确代码
bannerList = new ArrayList<>(slidingBanner.subList(0, SLIDING_SIZE));

提示

在使用Redis进行缓存对象时,对于被缓存的对象,由于JSON序列化工具Jackson的一些限制,必须使用lombok的@Data和@AllArgsConstructor来修饰,否者能出现缓存进了Redis但无法反序列化的问题。切记不能将被缓存对象声明成final!
具体可参见参见https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值