skip to Main Content

I am using Spring Data Redis in order to cache some data using @Cacheable. I have multiple types of objects that need to be cached and I need the data from Redis to be in JSON format. I know that, by default, the serializer used is JdkSerializationRedisSerializer, but with is the cached data is not human readable.

I order to save the data in JSON format I wanted to use GenericJackson2JsonRedisSerializer and I’ve created a custom ObjectMapper too:

  public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory cf) {

    ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().failOnEmptyBeans(false)
        .failOnUnknownProperties(false)
        .indentOutput(false)
        .serializationInclusion(JsonInclude.Include.NON_NULL)
        .modules(
            // Optional
            new Jdk8Module(),
            // Dates/Times
            new JavaTimeModule()
        )
        .featuresToDisable(
            SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
            DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,
            SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
        ).build();


    GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(cf);
    redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);
    redisTemplate.setHashKeySerializer(genericJackson2JsonRedisSerializer);
    redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
    redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
    return redisTemplate;

Using this RedisTemplate doesn’t work and I always get back this error:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to <some class>

As I understood, when deserializing, Jackson doesn’t know the type of the specific object since it’s Object and creates a LinkedHashMap to hold the data. Maybe I am wrong with this, but how can I achieve saving the cached data as JSON for multiple types of objects with @Cacheble?

2

Answers


  1. You are right, you can achieve saving multiple types with GenericJackson2JsonRedisSerializer. But in your example, you provide custom ObjectMapper to GenericJackson2JsonRedisSerializer and GenericJackson2JsonRedisSerializer doesn’t configure Jackson’s default typing for you (you can check default constructor logic in GenericJackson2JsonRedisSerializer). You have to tune it on your own and add this to your ObjectMapper

    objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
    

    This will include type information to JSON. Like this

    {
      "@class": "com.example.Foo",
      "field": "bar"
    }
    
    Login or Signup to reply.
  2. Since 2.10 ObjectMapper better to use

    activateDefaultTyping(mapper.polymorphicTypeValidator, ObjectMapper.DefaultTyping.NON_FINAL)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search