为什么Jackson redis serializer启用 USE_LONG_FOR_INTS 不起作用?

作者站长头像
站长
· 阅读数 8

我最近才知道Jackson通过开启配置USE_LONG_FOR_INTS可以将整型数据默认转换为Long类型,于是我将我的redisTemplate配置如下:

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        ObjectMapper objectMapper = new ObjectMapper();
        // 开启默认转换Long类型配置
        objectMapper.enable(DeserializationFeature.USE_LONG_FOR_INTS);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());

        template.setDefaultSerializer(jackson2JsonRedisSerializer);

        return template;
    }

但是并没有像我预想的一样:

    @Test
    void test() throws JsonProcessingException {
        redisTemplate.opsForValue().set("key", 11);
        System.out.println(redisTemplate.opsForValue().get("key").getClass());
    }

上面测试代码会打印Integer而非Long。

我仔细跟踪了下源码,发现大概是因为反序列化时执行的是这个函数com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer.Vanilla#deserializeWithType,这个函数中并没有判断当前是否开启了USE_LONG_FOR_INTS,只会判断是否开启了USE_BIG_INTEGER_FOR_INTS

我想知道咋样才能让Jackson默认返回Long类型,还是说没有办法了,只能写一个工具类每个取到返回值时自己做类型转换。

回复
1个回答
avatar
test
2024-07-05

你可以创建一个自定义的反序列化器,然后在反序列化时将整数值转换为 Long 类型。

public class CustomDeserializer extends JsonDeserializer<Object> {
    private final UntypedObjectDeserializer delegate;

    public CustomDeserializer() {
        this.delegate = new UntypedObjectDeserializer(null, null);
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object value = delegate.deserialize(p, ctxt);
        if (value instanceof Integer) {
            return ((Integer) value).longValue();
        }
        return value;
    }
}

然后把你创建的自定义反序列化器添加到 Jackson 的配置中:


@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new SimpleModule().addDeserializer(Object.class, new CustomDeserializer()));

    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

    template.setKeySerializer(RedisSerializer.string());
    template.setHashKeySerializer(RedisSerializer.string());

    template.setDefaultSerializer(jackson2JsonRedisSerializer);

    return template;
}
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容