首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring MVC JSON 日期格式化全攻略:全域配置與欄位級註解

     編輯:Java 相關知識

問題背景

Jackson 預設將 java.util.Date 序列化為時間戳 (long 毫秒數),前端需自行格式化。期望直接輸出 yyyy-MM-dd HH:mm:ss 等可讀格式。

方案一:全域配置 ObjectMapper (推薦)

Spring 4.x / 5.x XML 配置

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="com.example.config.CustomObjectMapper"/>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

CustomObjectMapper 實現

public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper() {
        // 日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        this.setDateFormat(sdf);
        // 禁用時間戳輸出
        this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 可選:統一處理 Java 8 時間類型
        this.registerModule(new JavaTimeModule());
    }
}

Spring Boot 2.x+ 自動配置

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.registerModule(new JavaTimeModule()); // 支援 LocalDateTime 等
        return mapper;
    }
}

// 或 application.yml
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false

方案二:欄位級 @JsonFormat 註解 (彈性控制)

public class Order {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate shipDate;

    @JsonFormat(pattern = "HH:mm:ss")
    private LocalTime dailyTime;

    @JsonFormat(shape = JsonFormat.Shape.NUMBER) // 強制輸出時間戳
    private Date legacyField;
}

方案三:自訂 JsonSerializer (完全控制)

public class CustomDateSerializer extends JsonSerializer<Date> {
    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    static { SDF.setTimeZone(TimeZone.getTimeZone("GMT+8")); }

    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(SDF.format(value));
    }
}

// 使用
public class Entity {
    @JsonSerialize(using = CustomDateSerializer.class)
    private Date specialDate;
}

Java 8 時間 API (java.time) 最佳實踐

強烈建議遷移至 LocalDateTime, LocalDate, Instant 等不可變、線程安全類型。

// 依賴 jackson-datatype-jsr310 (Spring Boot 已內傳)
mapper.registerModule(new JavaTimeModule());

// 實體類
public class Event {
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startTime;

    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate eventDate;

    // Instant 預設輸出 ISO-8601: 2023-10-01T12:30:00Z
    private Instant createdAt;
}

反序列化 (請求參數綁定) 配置

// 全域接受多種日期格式
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 或針對特定格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; // 同時支援輸入輸出

常見問題對照表

現象原因解決
輸出仍為時間戳未關閉 WRITE_DATES_AS_TIMESTAMPSmapper.configure(..., false)
時區偏移 8 小時預設 UTC,未設時區setTimeZone(GMT+8) 或 @JsonFormat(timezone="GMT+8")
LocalDateTime 報錯缺 JavaTimeModuleregisterModule(new JavaTimeModule())
日期字串解析失敗格式不匹配@JsonFormat(pattern=...) 指定輸入格式
XML 配置不生效Spring Boot 不讀取 mvc:annotation-driven改用 @Configuration + WebMvcConfigurer
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved