如何使用GenericJackson2JsonRedisSerializer

Dan*_*ana 13 java spring caching redis

我正在使用 Spring Data Redis 来缓存一些数据@Cacheable。我有多种类型的对象需要缓存,并且我需要 Redis 中的数据为 JSON 格式。我知道,默认情况下,使用的序列化器是JdkSerializationRedisSerializer,但是缓存的数据不是人类可读的。

我为了将数据保存为我想要使用的 JSON 格式GenericJackson2JsonRedisSerializer,并且我ObjectMapper也创建了一个自定义格式:

  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;
Run Code Online (Sandbox Code Playgroud)

使用这个RedisTemplate不起作用,我总是得到这个错误:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to <some class>
Run Code Online (Sandbox Code Playgroud)

据我了解,反序列化时,杰克逊不知道特定对象的类型,因为它是Object并创建一个LinkedHashMap来保存数据。也许我的想法是错的,但是如何使用@Cacheble将多种类型的对象的缓存数据保存为JSON?

Ale*_*lia 13

你是对的,你可以用 来实现保存多种类型GenericJackson2JsonRedisSerializer。但在您的示例中,您提供了自定义ObjectMapperGenericJackson2JsonRedisSerializerGenericJackson2JsonRedisSerializer没有为您配置Jackson 的默认类型GenericJackson2JsonRedisSerializer(您可以在 中检查默认构造函数逻辑)。您必须自己调整它并将其添加到您的 ObjectMapper

objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
Run Code Online (Sandbox Code Playgroud)

这将包括 JSON 的类型信息。像这样

{
  "@class": "com.example.Foo",
  "field": "bar"
}
Run Code Online (Sandbox Code Playgroud)


小智 5

从 2.10 开始,ObjectMapper 更好用

activateDefaultTyping(mapper.polymorphicTypeValidator, ObjectMapper.DefaultTyping.NON_FINAL)
Run Code Online (Sandbox Code Playgroud)