學(xué)習(xí)目標(biāo)
快速學(xué)會(huì)通過(guò)注解@JsonComponent
自定義日期格式化的序列化器猬腰。
快速查閱
專題閱讀:《SpringBoot 布道系列》
源碼下載:SpringBoot Date Format Anno
— Hey Man店量,Don't forget to Star or Fork . —
使用教程
根據(jù)官方文檔 Custom JSON Serializers and Deserializers ,想要接管Jackson的JSON的序列化和反序列化效扫,只需通過(guò)注解
@JsonComponent
來(lái)聲明其靜態(tài)內(nèi)部類即可俱恶。
首先根據(jù)項(xiàng)目要求提供自定義的日期序列化器和反序列化器帖族,其中包括:
DateJsonSerializer extends JsonSerializer<Date>
表示將Date格式化為日期字符串。DateJsonDeserializer extends JsonDeserializer<Date>
表示將日期字符串解析為Date日期逊抡。
/**
* 全局日期格式化
*/
@JsonComponent
public class DateFormatConfig {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 日期格式化
*/
public static class DateJsonSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(dateFormat.format(date));
}
}
/**
* 解析日期字符串
*/
public static class DateJsonDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
try {
return dateFormat.parse(jsonParser.getText());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
}
然后提供相應(yīng)的測(cè)試信息,這里以查詢用戶為例:
/**
* 查詢用戶信息
*/
@RestController
public class UserController {
@GetMapping("/")
public User get() {
return new User("1", "socks", "123456", new Date(), "GMT");
}
}
/**
* 用戶信息
*/
public class User {
private String userId;
private String username;
private String password;
private Date createTime;
private String timezone;
public User(String userId, String username, String password, Date createTime, String timezone) {
this.userId = userId;
this.username = username;
this.password = password;
this.createTime = createTime;
this.timezone = timezone;
}
//省略getters&setters
}
大功告成零酪,接下來(lái)啟動(dòng)應(yīng)用并訪問(wèn) http://127.0.0.1:8080 冒嫡,可以拿到正確結(jié)果:
{
"userId": "1",
"username": "socks",
"password": "123456",
"createTime": "2018-12-26 01:03:25"
}
除了日期格式化解析之外,我們還可以在DateFormatConfig
注入業(yè)務(wù)變量四苇,例如根據(jù)當(dāng)前登錄人的所屬時(shí)區(qū)(雖然SimpleDateFormat
默認(rèn)讀取了當(dāng)?shù)貢r(shí)區(qū)灯谣,但在實(shí)際的國(guó)際化系統(tǒng)中,用戶的所屬時(shí)區(qū)是指其在系統(tǒng)錄入的所屬時(shí)區(qū)蛔琅,而不是指當(dāng)?shù)貢r(shí)區(qū)胎许。例如Tony這個(gè)用戶賬號(hào)掛在GMT+0時(shí)區(qū),但此時(shí)他出差在香港使用罗售,系統(tǒng)仍需要按照GMT+0時(shí)區(qū)來(lái)顯示時(shí)間)辜窑,為了解決這個(gè)問(wèn)題,此時(shí)我們可以在DateFormatConfig
注入當(dāng)前登錄人然后改變?nèi)掌诠ぞ哳惖?code>TimeZone來(lái)動(dòng)態(tài)修改時(shí)區(qū)寨躁。
根據(jù)當(dāng)前登錄人動(dòng)態(tài)展示時(shí)區(qū):
/**
* 全局日期格式化
*/
@JsonComponent
public class DateFormatConfig {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z") {
@Override
public Date parse(String source) throws ParseException {
try {
if (StringUtils.isEmpty(source)) {
return null;
}
return super.parse(source);
} catch (Exception e) {
return new StdDateFormat().parse(source);
}
}
};
private static UserController userController;//這里是指獲取當(dāng)前登錄人的工具類
@Autowired
public void setUserController(UserController userController) {
DateFormatConfig.userController = userController;
}
/**
* 日期格式化
*/
public static class DateJsonSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
//獲取當(dāng)前登錄人的所屬時(shí)區(qū)
dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));
//格式化日期
jsonGenerator.writeString(dateFormat.format(date));
}
}
/**
* 解析日期字符串
*/
public static class DateJsonDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
try {
//獲取當(dāng)前登錄人的所屬時(shí)區(qū)
dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));
//解析日期
return dateFormat.parse(jsonParser.getText());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
}
修改完后重新啟動(dòng)應(yīng)用并訪問(wèn) http://127.0.0.1:8080 穆碎,可以拿到正確結(jié)果:
{
"userId": "1",
"username": "socks",
"password": "123456",
"createTime": "2018-12-25 17:35:50 +0000",
"timezone": "GMT"
}
小結(jié)
1、使用注解@JsonComponent
可以快速自定義日期格式化的序列化器职恳,免除傳統(tǒng)通過(guò)模塊注冊(cè)的煩惱所禀。
2方面、使用注解@JsonComponent
實(shí)現(xiàn)與當(dāng)?shù)責(zé)o關(guān)的動(dòng)態(tài)時(shí)區(qū)的精髓就在于將獲取當(dāng)前等人的方法寫在解析日期和格式化日期的代碼里。
3色徘、使用注解@JsonComponent
是直接處理String和Date的相互轉(zhuǎn)換的恭金,所以要注意空串問(wèn)題。例如dateFormat.parse()要預(yù)防空串褂策。