Closed
Description
we met an issue after upgrading spring-data-redis from 2.6.x to 2.7.x.
we have a class named Config
@Data
public class Config {
private int count;
private int[] available;
}
a json string is accessible in 2.6.x as below
{
"@class":"some.Config",
"count":1,
"available":[
0,
1
]
}
but meet exception when accessing this json in 2.7.x
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unexpected token (VALUE_NUMBER_INT), expected VALUE_STRING: need JSON String that contains type id (for subtype of [I)
at [Source: (byte[])"{"@class":"some.Config","count":1,"available":[0,1]}"; line: 1, column: 48] (through reference chain: some.Config["available"]); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_INT), expected VALUE_STRING: need JSON String that contains type id (for subtype of [I)
at [Source: (byte[])"{"@class":"some.Config","count":1,"available":[0,1]}"; line: 1, column: 48] (through reference chain: some.Config["available"])
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:157)
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:135)
at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:360)
at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:62)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:191)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:97)
at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:54)
RedisTemplate as below:
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(lettuceConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
We found change in this commit, then we customize an ObjectMapper:
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
return mapper;
}
and we make some changes in RedisTemplate definition:
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(lettuceConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
return redisTemplate;
}
it works.
All we do is just revert this back. Is there any workaround or something we miss to avoid this in production environment?
Thanks.