V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
JasonLaw
V2EX  ›  程序员

GenericJackson2JsonRedisSerializer 序列化会存在多余的双引号,怎么解决?

  •  
  •   JasonLaw · 2021-12-01 17:52:26 +08:00 · 1246 次点击
    这是一个创建于 1122 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RedisTemplate 如下:

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        ObjectMapper objectMapper = new ObjectMapper();
        PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
                                                                    .allowIfSubType(Object.class)
                                                                    .build();
        objectMapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_FINAL);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
        return redisTemplate;
    }
    

    执行以下代码后

    redisTemplate.opsForValue()
                 .set("k", "v");
    

    get k 的结果如下,会有多余的双引号,要怎么解决呢?只能使用 StringRedisSerializer 吗?

    第 1 条附言  ·  2021-12-07 21:53:57 +08:00

    通过extends GenericJackson2JsonRedisSerializer,然后redisTemplate.setValueSerializer(new CustomGenericJackson2JsonRedisSerializer());解决了这个问题。

    class CustomGenericJackson2JsonRedisSerializer extends GenericJackson2JsonRedisSerializer {
    
        private static final ObjectMapper OBJECT_MAPPER;
    
        static {
            OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());
            // https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
            PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
                                                                        .allowIfSubType(Object.class)
                                                                        .build();
            OBJECT_MAPPER.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        }
    
        public CustomGenericJackson2JsonRedisSerializer() {
            super(OBJECT_MAPPER);
        }
    
        @Override
        public byte[] serialize(Object source) throws SerializationException {
            if (source instanceof String) {
                return ((String) source).getBytes(StandardCharsets.UTF_8);
            } else {
                return super.serialize(source);
            }
        }
    }
    
    5 条回复    2021-12-07 21:55:31 +08:00
    chendy
        1
    chendy  
       2021-12-01 18:37:02 +08:00
    json 里的字符串带引号
    所以按照 json 格式序列化字符串也带引号
    只要字符串的话 StringRedisSerializer 就够用了
    JasonLaw
        2
    JasonLaw  
    OP
       2021-12-01 18:41:52 +08:00 via iPhone
    @chendy #1 代码里面执行系列化和反序列化?相当于使用 RedisTemplate<String, String>,而不是 RedisTemplate<String, Object>?
    billly
        3
    billly  
       2021-12-02 09:29:56 +08:00
    json 就是这样的啊,只要它能正确反序列化,也没什么问题吧
    gadfly3173
        4
    gadfly3173  
       2021-12-02 17:44:59 +08:00
    这个算是 GenericJackson2JsonRedisSerializer 的缺陷,也可以说是妥协。因为这个序列化类是用来处理 json 的,也就是[]{}之类的,突然冒出来个无法识别的东西,又不知道它是不是真的是字符串,所以使用双引号来表示这个值确实是字符串。觉得这样不能接受的话,就在你能确定结果一定是字符串的地方用 StringRedisTemplate 就行了。
    JasonLaw
        5
    JasonLaw  
    OP
       2021-12-07 21:55:31 +08:00
    @chendy #1
    @billly #3
    @gadfly3173 #4

    我通过 extends GenericJackson2JsonRedisSerializer ,然后 redisTemplate.setValueSerializer(new CustomGenericJackson2JsonRedisSerializer());解决了这个问题。详细见附言。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2778 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 609ms · UTC 07:46 · PVG 15:46 · LAX 23:46 · JFK 02:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.