如何使用redis序列化Java Instant类型

Noe*_*oel 5 java spring instant redis

我正在使用 spring boot 2.0.3 和 spring-boot-starter-data-redis。还使用 jackson-datatype-jsr310。

我想将对象存储到redis中。

对象(MyObj):

String text;
Instant instant;
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

@Test
public void test() {

    ListOperations<String, MyObj> listOps = redisTemplate.opsForList();

    MyObj o1 = new MyObj();
    o1.setText("foo");
    o1.setInstant(Instant.now());

    listOps.leftPush("foo", o1);

    MyObj o2 = new MyObj();
    o2.setText("bar");
    o2.setInstant(Instant.now());

    listOps.leftPush("foo", o2);

    List<MyObj> list = listOps.range("foo", 0, -1);

    for (MyObj o : list) {
        System.out.println(o.getText());
        System.out.println(o.getInstant());
    }

}
Run Code Online (Sandbox Code Playgroud)

在我的 RedisConfig 中:

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
Run Code Online (Sandbox Code Playgroud)

但是当我推入redis时,出现以下错误:

org.springframework.data.redis.serializer.SerializationException:无法读取JSON:无法构造实例java.time.Instant(不存在创建者,如默认构造):无法从对象值反序列化(没有基于委托或属性的创建者)

如何使用Redis序列化java即时类型?

任何意见将不胜感激。

小智 0

虽然这是一篇相当老的文章,但我最近遇到了这个问题,并在决定读取类文件之前进行了懒人搜索并发现了这个问题。我发现您可以轻松地ObjectMapper用自定义的覆盖默认值。使用setObjectMapper(ObjectMapper objectMapper)序列化器上的方法来覆盖默认值。

// Taken from Jackson library
public class Jackson2JsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    private final JavaType javaType;

    private ObjectMapper objectMapper = new ObjectMapper();
    
    // truncated
    
    public void setObjectMapper(ObjectMapper objectMapper) {

        Assert.notNull(objectMapper, "'objectMapper' must not be null");
        this.objectMapper = objectMapper;
    }


Run Code Online (Sandbox Code Playgroud)

您只需要创建一个 ObjectMapper 并注册 JavaTime.Module ,如下所示

public static ObjectMapper dateMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;

     Jackson2JsonRedisSerializer<MyObj> valueSerializer = new 
         Jackson2JsonRedisSerializer<>(MyObj.class);
     valueSerializer.setObjectMapper(dateMapper());
    }
Run Code Online (Sandbox Code Playgroud)

disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)默认行为的转变。