如何强制JavaTimeModule将LocalDateTime序列化为Long类型时间戳?
解决LocalDateTime转Map时序列化为时间戳的问题
问题的核心在于:LocalDateTime是无时区的日期时间类型,而时间戳是基于UTC纪元的毫秒数,必须结合时区才能完成转换。同时,SerializationFeature.WRITE_DATES_AS_TIMESTAMPS=true默认只对java.util.Date这类旧日期类型生效,对Java 8引入的LocalDateTime等新类型不产生作用,这就是你配置后没效果的原因。
以下是两种不需要修改MyItem类的解决方案:
方案一:自定义LocalDateTime序列化器
通过给JavaTimeModule添加自定义序列化逻辑,明确指定时区并将LocalDateTime转换为毫秒时间戳:
MyItem item = new MyItem(); item.setCreatedAt(LocalDateTime.now()); ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); // 自定义序列化器:将LocalDateTime转为UTC时区的毫秒时间戳 javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 绑定UTC时区,转换为Instant后获取毫秒数 long timestamp = value.atZone(ZoneId.of("UTC")).toInstant().toEpochMilli(); gen.writeNumber(timestamp); } }); objectMapper.registerModule(javaTimeModule); Map<String, Object> fieldsToSetOnInsert = objectMapper.convertValue(item, Map.class);
如果需要使用系统默认时区,将ZoneId.of("UTC")替换为ZoneId.systemDefault()即可。
方案二:配置JavaTimeModule的全局序列化规则
通过配置JavaTimeModule并指定默认时区,让LocalDateTime序列化为时间戳:
MyItem item = new MyItem(); item.setCreatedAt(LocalDateTime.now()); ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); // 开启时间戳序列化,并设置默认时区(必须指定,否则LocalDateTime无法转时间戳) javaTimeModule.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true); objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); objectMapper.registerModule(javaTimeModule); Map<String, Object> fieldsToSetOnInsert = objectMapper.convertValue(item, Map.class);
关键说明
- 必须指定时区:
LocalDateTime本身不包含时区信息,无法直接计算UTC纪元的毫秒数,所以必须绑定一个时区(如UTC、系统时区)才能完成转换。 - 无需修改
MyItem类:两种方案都是通过配置ObjectMapper的序列化规则实现,完全不需要改动目标类的代码。
内容的提问来源于stack exchange,提问作者breakline
相关产品推荐
相关产品推荐

