Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default解决方案

当使用 RedisTemplate 将包含 LocalDateTime 类型字段的对象存储到 Redis 中时,可能会遇到如下问题和解决方案:

Bug复现

问题描述:
在使用 RedisTemplate 向 Redis 中存储包含 LocalDateTime 类型字段的对象时,可能会遇到以下错误:

org.springframework.data.redis.serializer.SerializationException: Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default

错误分析:
默认情况下,Jackson 库不支持 Java 8 的 LocalDateTime 类型的序列化和反序列化,因此在将对象序列化为 JSON 字符串时会抛出 SerializationException 异常。

错误堆栈示例:

org.springframework.data.redis.serializer.SerializationException: Could not write JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.ArrayList[0]->com.example.model.Comments["createdTime"])
    at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.serialize(Jackson2JsonRedisSerializer.java:151)
    at org.springframework.data.redis.core.AbstractOperations.rawValue(AbstractOperations.java:128)
    at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:251)
    at com.example.service.CommentService.saveComments(CommentService.java:45)
    ...

解决过程

解决方案:

  1. 添加依赖: 首先确保在项目中添加 com.fasterxml.jackson.datatype:jackson-datatype-jsr310 依赖,这是 Jackson 库的一个扩展模块,用于支持 Java 8 的日期和时间类型。

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.13.0</version>
    </dependency>
    
  2. 自定义序列化器和反序列化器: 在 Redis 配置中,需要自定义 Jackson 的 ObjectMapper,以处理 LocalDateTime 类型的字段。这包括注册 JavaTimeModule,并配置 LocalDateTime 的序列化和反序列化规则。

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.util.List;
    
    @Configuration
    public class RedisConfig {
    
        @Bean(name = "commentListRedisTemplate")
        public RedisTemplate<String, List<Comments>> commentListRedisTemplate(
                RedisConnectionFactory redisConnectionFactory) {
    
            RedisTemplate<String, List<Comments>> template = new RedisTemplate<>();
            template.setConnectionFactory(redisConnectionFactory);
            template.setKeySerializer(new StringRedisSerializer());
    
            ObjectMapper objectMapper = new ObjectMapper()
                    .registerModule(new JavaTimeModule())
                    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    
            Jackson2JsonRedisSerializer<List<Comments>> serializer =
                    new Jackson2JsonRedisSerializer<>(List.class);
            serializer.setObjectMapper(objectMapper);
    
            template.setValueSerializer(serializer);
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setHashValueSerializer(serializer);
    
            return template;
        }
    }
    
  3. 在实体类中配置: 确保在包含 LocalDateTime 类型字段的实体类中,使用 Jackson 注解对该字段进行配置,包括序列化器、反序列化器和日期时间格式。

    import com.fasterxml.jackson.annotation.JsonFormat;
    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
    import java.time.LocalDateTime;
    
    public class Comments {
    
        @JsonSerialize(using = LocalDateTimeSerializer.class)
        @JsonDeserialize(using = LocalDateTimeDeserializer.class)
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private LocalDateTime createdTime;
    
        // 其他字段和方法...
    }
    

总结

通过上述步骤,解决了在使用 RedisTemplate 存储包含 LocalDateTime 类型字段的对象时遇到的序列化问题。通过添加适当的 Jackson 扩展依赖,并在 Redis 配置中自定义序列化器和反序列化器,以及在实体类中配置 Jackson 注解,确保了 LocalDateTime 类型字段能够正确地序列化为 JSON 字符串,并在需要时正确地反序列化回对象。这样就能够顺利地将对象存储到 Redis 中,并从中检索出来,同时保持了日期时间的格式和时区的一致性。

  • 28
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是行东啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值