测试代码:
package com.sanss.prc.alarm.jul;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import javax.annotation.Resource;
@SpringBootTest
@Slf4j
public class DatePrintTest {
plain @Resource ObjectMapper objectMapper;
plain @Test
void testDatePrint() throws JsonProcessingException {
// serialize test
MeetingScreenOrderResp.Record record = new MeetingScreenOrderResp.Record();
record.setOrderTime(new Date());
log.info("log info print:{}", record.getOrderTime());
log.info("obj mapper:{}", objectMapper.writeValueAsString(record.getOrderTime()));
// deserialize test
String[] dateFormats = {"\"2024-07-30 14:30:00\"", "\"2024-07-30T14:30:00\"", "\"2024-07-30T14:30:00Z\"",
"\"2024-07-30T14:30:00+08:00\"", "1722504600000" // 毫秒时间戳
};
for (String dateStr : dateFormats) {
try {
MeetingScreenOrderResp.Record dto =
objectMapper.readValue("{\"orderTime\": " + dateStr + "}", MeetingScreenOrderResp.Record.class);
log.info("成功解析: {} => {}", dateStr, dto.getOrderTime());
} catch (Exception e) {
log.info("解析失败: {} - {}", dateStr, e.getMessage());
}
}
}
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义日期序列化
// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// objectMapper.setDateFormat(df);
// 关闭反序列化时写入时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 未知属性不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
pojo:
/**
* 订单时间(格式:yyyy-MM-dd hh:mm:ss)。
*/
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date orderTime;
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:27 : log info print:Tue Jul 30 10:48:54 SGT 2024
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30T10:48:54.930+08:00"
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30 14:30:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30 14:30:00": not a valid representation (error: Failed to parse Date value '2024-07-30 14:30:00': Cannot parse date "2024-07-30 14:30:00": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null))
at [Source: (String)"{"orderTime": "2024-07-30 14:30:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30T14:30:00" => Tue Jul 30 14:30:00 SGT 2024
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30T14:30:00Z" => Tue Jul 30 22:30:00 SGT 2024
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30T14:30:00+08:00" => Tue Jul 30 14:30:00 SGT 2024
2024-07-30 10:48:54 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: 1722504600000 => Thu Aug 01 17:30:00 SGT 2024
objectMapper 未设置 dateformat,@jsonFormat 注解未生效
2024-07-30T10:48:54.930+08:00
日期字符串 | 解析结果 |
---|---|
“2024-07-30 14:30:00” | 解析失败 |
“2024-07-30T14:30:00” | 成功解析 |
“2024-07-30T14:30:00Z” | 成功解析 |
“2024-07-30T14:30:00+08:00” | 成功解析 |
1722504600000 | 成功解析 |
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义日期序列化
// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// objectMapper.setDateFormat(df);
// 关闭反序列化时写入时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 未知属性不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
pojo:
/**
* 订单时间(格式:yyyy-MM-dd hh:mm:ss)。
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date orderTime;
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:27 : log info print:Tue Jul 30 10:50:32 SGT 2024
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30T10:50:32.868+08:00"
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30 14:30:00" => Tue Jul 30 14:30:00 SGT 2024
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00Z" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00Z": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00Z"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00+08:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00+08:00": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00+08:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: 1722504600000 => Thu Aug 01 17:30:00 SGT 2024
objectMapper 未设置 dateformat,@jsonFormat 注解生效
2024-07-30T10:50:32.868+08:00
日期字符串 | 解析结果 |
---|---|
“2024-07-30 14:30:00” | 解析成功 |
“2024-07-30T14:30:00” | 解析失败 |
“2024-07-30T14:30:00Z” | 解析失败 |
“2024-07-30T14:30:00+08:00” | 解析失败 |
1722504600000 | 成功解析 |
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义日期序列化
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(df);
// 关闭反序列化时写入时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 未知属性不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
pojo:
/**
* 订单时间(格式:yyyy-MM-dd hh:mm:ss)。
*/
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date orderTime;
2024-07-30 10:53:22 INFO [alarm,,] --- [ Thread-7] com.xxl.job.core.server.EmbedServer .run:82 : >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:27 : log info print:Tue Jul 30 10:53:23 SGT 2024
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30 10:53:23"
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30 14:30:00" => Tue Jul 30 14:30:00 SGT 2024
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": not a valid representation (error: Failed to parse Date value '2024-07-30T14:30:00': Unparseable date: "2024-07-30T14:30:00")
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00Z" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00Z": not a valid representation (error: Failed to parse Date value '2024-07-30T14:30:00Z': Unparseable date: "2024-07-30T14:30:00Z")
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00Z"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00+08:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00+08:00": not a valid representation (error: Failed to parse Date value '2024-07-30T14:30:00+08:00': Unparseable date: "2024-07-30T14:30:00+08:00")
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00+08:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:53:23 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: 1722504600000 => Thu Aug 01 17:30:00 SGT 2024
objectMapper 设置 dateformat,@jsonFormat 注解未生效
2024-07-30 10:53:23
日期字符串 | 解析结果 |
---|---|
“2024-07-30 14:30:00” | 解析成功 |
“2024-07-30T14:30:00” | 解析失败 |
“2024-07-30T14:30:00Z” | 解析失败 |
“2024-07-30T14:30:00+08:00” | 解析失败 |
1722504600000 | 成功解析 |
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义日期序列化
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(df);
// 关闭反序列化时写入时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 未知属性不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
pojo:
/**
* 订单时间(格式:yyyy-MM-dd hh:mm:ss)。
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date orderTime;
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:27 : log info print:Tue Jul 30 10:54:36 SGT 2024
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30 10:54:36"
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30 14:30:00" => Tue Jul 30 14:30:00 SGT 2024
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00Z" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00Z": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00Z"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00+08:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00+08:00": expected format "yyyy-MM-dd HH:mm:ss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00+08:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 10:54:36 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: 1722504600000 => Thu Aug 01 17:30:00 SGT 2024
objectMapper 设置 dateformat,@jsonFormat 注解生效
2024-07-30 10:54:36
日期字符串 | 解析结果 |
---|---|
“2024-07-30 14:30:00” | 解析成功 |
“2024-07-30T14:30:00” | 解析失败 |
“2024-07-30T14:30:00Z” | 解析失败 |
“2024-07-30T14:30:00+08:00” | 解析失败 |
1722504600000 | 成功解析 |
- | objectMapper 设置 dateformat | objectMapper 不设置 dateformat |
---|---|---|
@JsonFormat 字段 注解存在 | 情况四 | 情况二 |
@JsonFormat 字段注解不存在 | 情况三 | 情况一 |
请根据测试,分析 objectMapper 中 dateformat 配置项 以及@jsonformat 注解对于序列化 反序列化的影响
/**
* 订单时间(格式:yyyy-MM-dd hh:mm:ss)。
*/
@JsonFormat(pattern = "yyyyMMddHHmmss", timezone = "GMT+8")
private Date orderTime;
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 自定义日期序列化
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(df);
// 关闭反序列化时写入时间戳
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
// 未知属性不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
2024-07-30 11:11:32 INFO [alarm,,] --- [ Thread-7] com.xxl.job.core.server.EmbedServer .run:82 : >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:27 : log info print:Tue Jul 30 11:11:32 SGT 2024
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30 11:11:32"
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: "2024-07-30 14:30:00" => Wed Dec 06 21:00:14 SGT 2023
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": expected format "yyyyMMddHHmmss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00Z" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00Z": expected format "yyyyMMddHHmmss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00Z"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:41 : 解析失败: "2024-07-30T14:30:00+08:00" - Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00+08:00": expected format "yyyyMMddHHmmss"
at [Source: (String)"{"orderTime": "2024-07-30T14:30:00+08:00"}"; line: 1, column: 15] (through reference chain: com.sanss.prc.model.alarm.model.dto.response.MeetingScreenOrderResp$Record["orderTime"])
2024-07-30 11:11:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:39 : 成功解析: 1722504600000 => Thu Aug 01 17:30:00 SGT 2024
反序列化时,JsonFormat 注解的 pattern 优先级高于 objectMapper 的 dateformat 配置,可以从以下错误信息中看出:
Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": expected format "yyyyMMddHHmmss"
JsonFormat 注解应当对序列化没有帮助,可以从情况二的测试结果中看出
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30T10:50:32.868+08:00"
总结:
对于序列化,objectMapper 来决定,JsonFormat 字段注解对于序列化没有任何帮助,补充测试可以直观看出.
jsonformat
指定的格式是 yyyyMMddHHmmss
,但是序列化的时候还是按照 objectMapper
指定的 yyyy-MM-dd HH:mm:ss
格式序列化的
对于objectMapper
未指定序列化格式时,jsonformat
指定的格式也未生效,参照情况二:
2024-07-30 10:50:32 INFO [alarm,,] --- [ main] com.sanss.prc.alarm.jul.DatePrintTest .testDatePrint:28 : obj mapper:"2024-07-30T10:50:32.868+08:00"
对于反序列化,JsonFormat 字段注解的优先级更高,同样可以从补充测试结果中看出:
Cannot deserialize value of type `java.util.Date` from String "2024-07-30T14:30:00": expected format "yyyyMMddHHmmss"
对于不带@JsonFormat 注解的情况,可以参考情况一,情况三
如果 objectMapper 没有设置 yyyy-MM-dd HH:mm:ss格式,那么这种时间格式无法被反序列化
如果 objectMapper 设置了 yyyy-MM-dd HH:mm:ss格式,那么这种时间格式可以被反序列化
ms 级时间戳无论如何都可以被反序列化
一般来说,为了给前端提供更好的时间格式,一般会在 objectMapper 设置时间格式,那么这种情况下,@JsonFormat 注解其实是可有可无的,情况三四可以佐证