Skip to content

GenericJackson2JsonRedisSerializer fails with Unexpected token when deserializing int[] with default typing #2361

Closed
@timbotetsu

Description

@timbotetsu

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions