解决宇道项目关于接收日期格式yyyy-MM-dd HH:mm:ss后端自动转为1970-01-01 00:00:00的问题
解决宇道项目关于接收日期格式yyyy-MM-dd HH:mm:ss后端自动转为1970-01-01 00:00:00的问题
- 问题描述
- 问题原因
- 解决方案
- 验证
问题描述
使用芋道项目在开发过程中发现新增语句中、查询语句自定义的日期,前端传输的格式为yyyy-MM-dd HH:mm:ss、后端接收到的数据为1970-01-01 00:00:00
问题原因
Spring Boot 默认使用 Jackson 进行反序列化,而 LocalDateTime 默认格式为 ISO_LOCAL_DATE_TIME(例如:2025-07-23T17:31:46)。而前端传的是 “yyyy-MM-dd HH:mm:ss”,不符合格式,所以 Jackson 无法解析,最后转成了默认值(即 1970-01-01T00:00:00)。
解决方案
在全局配置中通过配置支持字符串和时间戳双格式保留时间戳的兼容性,又支持前端传字符串(格式为 yyyy-MM-dd HH:mm:ss),参考 Spring 官方推荐的写法,自定义的兼容反序列化器,手动判断是字符串还是数字,具体示例代码如下:
@AutoConfiguration
@Slf4j
public class RtJacksonAutoConfiguration {@Bean@SuppressWarnings("InstantiationOfUtilityClass")public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {// 1.1 创建 SimpleModule 对象SimpleModule simpleModule = new SimpleModule();simpleModule// 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型.addSerializer(Long.class, NumberSerializer.INSTANCE).addSerializer(Long.TYPE, NumberSerializer.INSTANCE).addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE).addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE).addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE).addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)// 兼容时间规则.addDeserializer(LocalDateTime.class, new CompatibleLocalDateTimeDeserializer()).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
// .addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
// .addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);// 1.2 注册到 objectMapperobjectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));// 2. 设置 objectMapper 到 JsonUtilsJsonUtils.init(CollUtil.getFirst(objectMappers));log.info("[init][初始化 JsonUtils 成功]");return new JsonUtils();}
public class CompatibleLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Asia/Shanghai");@Overridepublic LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {if (p.currentToken().isNumeric()) {// 时间戳(毫秒)long timestamp = p.getLongValue();return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), DEFAULT_ZONE_ID);} else {// 字符串时间String str = p.getText().trim();if (str.isEmpty()) return null;return LocalDateTime.parse(str, DEFAULT_FORMATTER);}}
}
验证
到此完美解决该问题