背景:
????????解決前端傳入時間參數格式不固定場景,避免接收參數報錯時間格式不能序列化。
一、概述
????????在 Java 后端開發中,處理 JSON 數據時,經常需要對日期時間字段進行反序列化。Java 中常用的日期時間類型是 java.time.LocalDateTime,但前端傳入的數據格式可能千差萬別,如 "2025-04-05"、"2025-04-05 13:30:00" 或者僅僅是一個時間字符串 "13:30:00"。為了應對這些靈活的時間格式,我們編寫了一個自定義的 Jackson 反序列化器 —— FlexibleLocalDateTimeDeserializer
二、設計目標
FlexibleLocalDateTimeDeserializer 的主要目標是:
- 兼容多種時間格式:支持 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss 和 HH:mm:ss。
- 避免反序列化失敗:當遇到不規范的時間格式時,提供合理的默認行為或拋出明確錯誤。
- 與業務數據模型解耦:通過 Jackson 注解綁定到 DTO 字段,無需修改業務邏輯代碼即可完成適配。
三、實現細節
通過正則表達式實現格式處理
- 包含空格 → 使用完整日期時間格式;
- 匹配日期格式 → 補上 23:59:59;
- 匹配時間格式 → 結合當前日期生成完整時間戳
定義序列化處理工具
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;public class FlexibleLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");@Overridepublic LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {String value = p.getText();if (value == null || ObjectUtil.isEmpty( value)) return null;try {if (value.contains(" ")) {return LocalDateTime.parse(value, DATE_TIME_FORMATTER);} else if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {String s = LocalDate.parse(value, DATE_FORMATTER).toString() + " 23:59:59";LocalDateTime parse = LocalDateTime.parse(s, DATE_TIME_FORMATTER);return parse;
// return LocalDate.parse(value, DATE_FORMATTER).atTime(LocalTime.MAX); // 存數據庫為第二天00:00:00} else if (value.matches("\\d{2}:\\d{2}:\\d{2}")) {LocalTime time = LocalTime.parse(value, TIME_FORMATTER);return LocalDateTime.now().with(time);}} catch (Exception e) {throw new RuntimeException("無法解析日期時間:" + value, e);}throw new RuntimeException("未知的日期格式:" + value);}
}
四、實際使用示
在接收前端的dto字段參數加上注解即可。這時候前端傳入yyyy-MM-dd、yyyy-MM-dd HH:mm:ss 和 HH:mm:ss格式都可以接收,可自定義填充日期格式。
@JsonFormat(shape = JsonFormat.Shape.STRING)
@JsonDeserialize(using = FlexibleLocalDateTimeDeserializerZero.class)
private LocalDateTime startdate;@JsonFormat(shape = JsonFormat.Shape.STRING)
@JsonDeserialize(using = FlexibleLocalDateTimeDeserializer.class)
private LocalDateTime enddate;