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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:44:08