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)
...
解决过程
解决方案:
-
添加依赖: 首先确保在项目中添加
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>
-
自定义序列化器和反序列化器: 在 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; } }
-
在实体类中配置: 确保在包含 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 中,并从中检索出来,同时保持了日期时间的格式和时区的一致性。
更多推荐
所有评论(0)