Jackson 預設將 java.util.Date 序列化為時間戳 (long 毫秒數),前端需自行格式化。期望直接輸出 yyyy-MM-dd HH:mm:ss 等可讀格式。
<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>
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());
}
}
@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
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;
}
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;
}
強烈建議遷移至 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_TIMESTAMPS | mapper.configure(..., false) |
| 時區偏移 8 小時 | 預設 UTC,未設時區 | setTimeZone(GMT+8) 或 @JsonFormat(timezone="GMT+8") |
| LocalDateTime 報錯 | 缺 JavaTimeModule | registerModule(new JavaTimeModule()) |
| 日期字串解析失敗 | 格式不匹配 | @JsonFormat(pattern=...) 指定輸入格式 |
| XML 配置不生效 | Spring Boot 不讀取 mvc:annotation-driven | 改用 @Configuration + WebMvcConfigurer |