ObjectMapper Redis序列化问题:自定义实体反序列化失败的解决方案咨询
解决方案:修复Redis中Foo实体的反序列化问题
你遇到的是Jackson类型信息处理与Redis序列化/反序列化的典型冲突问题,我来帮你一步步解决:
问题根源分析
你当前的配置使用了默认的activateDefaultTyping(),它默认采用JsonTypeInfo.As.WRAPPER_ARRAY方式存储类型信息——也就是把每个对象(包括集合)包裹在数组里,第一个元素是类名,第二个是对象内容。但反序列化根对象Foo时,Jackson期望根节点是数组(匹配WRAPPER_ARRAY格式),但实际存储的是JSON对象,因此抛出Unexpected token (START_OBJECT), expected START_ARRAY异常。
如果去掉类型配置,Jackson没有足够信息将JSON转换为Foo实例,只能退化为LinkedHashMap,进而导致ClassCastException。
正确的序列化配置调整
你需要修改ObjectMapper的类型信息处理方式,改用JsonTypeInfo.As.PROPERTY——这种方式会在JSON对象中添加@class字段存储类型信息,而非用数组包裹。修改后的配置如下:
@Bean public RedisSerializer<Object> serializer() { ObjectMapper mapper = new ObjectMapper(); // 调整类型信息处理逻辑:为非final类添加@class属性 mapper.activateDefaultTyping( mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY ); mapper.registerModule(new Jdk8Module()); mapper.registerModule(new JavaTimeModule()); mapper.addMixIn(Collection.class, HibernateCollectionMixIn.class); return new GenericJackson2JsonRedisSerializer(mapper); }
效果验证
调整后,Redis中存储的Foo实例格式会变为:
{ "@class": "com.foo.Foo", "attr1": "123456789", "attr2": { "@class": "java.util.HashSet", "elements": [1, 2, 3] }, "attr3": { "@class": "java.util.HashSet", "elements": [] } }
此时Jackson可以通过@class字段识别根对象为Foo,集合也能正确反序列化为HashSet<Long>,不会再抛出异常。
注意事项
- 如果Redis中已有旧格式的缓存数据,必须先清理,否则新的反序列化逻辑无法识别旧格式数据,依然会报错。
ObjectMapper.DefaultTyping.NON_FINAL的作用是仅给非final类添加类型信息,避免给Long这类基础final类型添加不必要的类型字段,减少JSON体积。
内容的提问来源于stack exchange,提问作者Mohit Sharma
相关产品推荐
相关产品推荐

