为什么Jackson redis serializer启用 USE_LONG_FOR_INTS 不起作用?
我最近才知道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类型,还是说没有办法了,只能写一个工具类每个取到返回值时自己做类型转换。
回答:
你可以创建一个自定义的反序列化器,然后在反序列化时将整数值转换为 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;
}
回答:
我测了下 这样是可以的
@Configurationpublic class Redis {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@PostConstruct
public void init() {
ObjectMapper objectMapper = new ObjectMapper();
// 开启默认转换Long类型配置
objectMapper.enable(DeserializationFeature.USE_LONG_FOR_INTS);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
}
}
以上是 为什么Jackson redis serializer启用 USE_LONG_FOR_INTS 不起作用? 的全部内容, 来源链接: utcz.com/p/945111.html