Jaskson精講第6篇-自定義JsonSerialize與Deser
Jackson是Spring Boot(SpringBoot)預設的JSON資料處理框架,但是其並不依賴於任何的Spring 庫。有的小夥伴以為Jackson只能在Spring框架內使用,其實不是的,沒有這種限制。它提供了很多的JSON資料處理方法、註解,也包括流式API、樹模型、資料繫結,以及複雜資料型別轉換等功能。它雖然簡單易用,但絕對不是小玩具,更多的內容我會寫成一個系列,5-10篇文章,請您繼續關注我。
本節繼續為大家介紹在Jackson序列化中經常遇到的一些特殊的資料型別,如LocalDateTime 。該如何進行序列化和反序列化。
一、LocalDateTime
反序列化異常
首先我們定義一個java POJO實體類,其中關鍵的成員變數時birthDate
,我們沒有采用Date資料型別,而是採用了Java8 新的日期型別LocalDateTime
,使用LocalDateTime
的好處我就不多說了,有很多的文章解釋說明。我們把精力放回到Jackson的JSON格式序列化與反序列化內容上來。
@Data
public class PlayerStar4 {
private String name; //姓名
private LocalDateTime birthDate; //出生日期
}
下面的程式碼,我們首先定義了一個PlayerStar4類的物件player,然後
- 使用writeValueAsString方法將player物件序列化為JSON字串jsonString
- 然後使用readValue方法將JSON字串jsonString ,反序列化為PlayerStar4類的物件
@Test
void testJSON2Object() throws IOException {
ObjectMapper mapper = new ObjectMapper();
PlayerStar4 player = new PlayerStar4();
player.setName("curry");//我並不知道庫裡的生日,這裡是編造的
player.setBirthDate(LocalDateTime.of(1986,4,5,12,50));
//將player物件以JSON格式進行序列化為String物件
String jsonString = mapper.writeValueAsString(player);
System.out.println(jsonString);
//將JSON字串反序列化為java物件
PlayerStar4 curry = mapper.readValue(jsonString, PlayerStar4.class);
System.out.println(curry);
}
但是上面的程式碼報錯了,從下圖中可以看出
- 將player物件序列化為JSON字串jsonString 的過程被正常執行了,但是LocalDateTime序列化之後的結果,是圖中”黃框中的黃框“內容。
- 將JSON字串反序列化的過程報錯了,因為Jackson預設情況下,根本不認識圖中”黃框中的黃框“內容這種LocalDateTime序列化之後的JSON字串資料結構。無法把它反序列化為java物件。
怎麼辦?我們需要自定義序列化及反序列化型別轉換器,有兩種方法
- 繼承StdConverter類,自定義實現String與LocalDateTime相互轉換
- 繼承JsonSerializer和JsonDeserializer類,自定義實現String與LocalDateTime相互轉換
二、方法一:繼承StdConverter類
繼承StdConverter類,將LocalDateTime序列化為String資料型別
public class LocalDateTimeToStringConverter extends StdConverter<LocalDateTime, String> {
static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
@Override
public String convert(LocalDateTime value) {
return value.format(DATE_FORMATTER);
}
}
繼承StdConverter類,將String資料型別反序列化為LocalDateTime
public class StringToLocalDatetimeConverter extends StdConverter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String value) {
return LocalDateTime.parse(value, LocalDateTimeToStringConverter.DATE_FORMATTER);
}
}
自定義的轉換器完成之後,我們就可以在對應的成員變數上,使用@JsonSerialize
指定序列化轉換器,@JsonDeserialize
指定反序列化轉換器。
@JsonSerialize(converter = LocalDateTimeToStringConverter.class)
@JsonDeserialize(converter = StringToLocalDatetimeConverter.class)
private LocalDateTime birthDate;
然後呼叫第一小節中的測試用例,就不會出現異常了。控制檯列印輸出結果如下,第一行是序列化結果JSON格式字串,第二行是Java 物件的toString()方法的列印結果。
{"name":"curry","birthDate":"1986-4-5 12:50:00"}
PlayerStar4(name=curry, birthDate=1986-04-05T12:50)
三、方法二:繼承JsonSerializer和JsonDeserializer類
繼承JsonSerializer<LocalDateTime>
類,將LocalDateTime序列化為String資料型別
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
String s = value.format(DATE_FORMATTER);
gen.writeString(s);
}
}
繼承JsonDeserializer<LocalDateTime>
類,將String資料型別反序列化為LocalDateTime
public class LocalDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
String str = p.getText();
return LocalDateTime.parse(str, LocalDateTimeSerializer.DATE_FORMATTER);
}
}
四、如果上面的你都沒看懂
對於相對小白的讀者,上面的自定義序列化及反序列化轉換過程你都沒懂,對於LocalDateTime的異常你也不要慌,Jackson已經給出瞭解決方案。
需要特別和大家強調的是LocalDateTimeSerializer和LocalDateTimeDeserializer其實並不需要我們自己去定義,因為Jackson已經幫我們定義好了。 之所以我還做了自定義的實現的介紹,是因為要為大家講解這個自定義序列化和反序列化型別轉換的實現過程,以後你再遇到其他的特殊的資料型別轉換,或者LocalDateTime型別的特殊日期格式等,都可以自己來定義JsonSerialize和JsonDeserialize來實現資料型別的轉換。
下面的這兩個類就是Jackson已經幫我們定義好的LocalDateTimeSerializer和LocalDateTimeDeserializer。
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
使用方法是在對應的成員變數上,使用@JsonSerialize
指定序列化轉換器,@JsonDeserialize
指定反序列化轉換器。
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime birthDate;
執行之後的序列化和反序列化結果,和方法一、方法二自定義的實現效果是一樣的。
歡迎關注我的部落格,裡面有很多精品合集
- 本文轉載註明出處(必須帶連線,不能只轉文字):。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1916/viewspace-2826312/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Jaskson精講第6篇-自定義JsonSerialize與Deserialize實現資料型別轉換JSON資料型別
- Jaskson精講第7篇-類繼承關係下的JSON序列化與反序列化JsonTypeInfo繼承JSON
- 精講RestTemplate第7篇-自定義請求失敗異常處理REST
- 屬性序列化自定義與字母表排序-JSON框架Jackson精解第3篇排序JSON框架
- 第一講:自定義服務整合原理講解
- @JsonCreator自定義反序列化函式-JSON框架Jackson精解第5篇JSON函式框架
- (第五講)自定義Spring Boot StarterSpring Boot
- MySQL講義第8講——資料更新之 DELETEMySqldelete
- 第216天:Angular—自定義指令(二)Angular
- 精講響應式WebClient第4篇-檔案上傳與下載Webclient
- 瘋狂Java講義第3版PDFJava
- 小書MybatisPlus第3篇-自定義SQLMyBatisSQL
- 小書MybatisPlus第5篇-Active Record模式精講MyBatis模式
- ABP AutoMapper與自定義MappingAPP
- 精講RestTemplate第9篇-如何透過HTTP Basic AuRESTHTTP
- MySQL講義第27講——select 查詢之自連線查詢MySql
- MySQL講義第 47 講——select 查詢之查詢練習(五)MySql
- 精講RestTemplate第6篇-檔案上傳下載與大檔案流式下載REST
- 精講響應式webclient第1篇-響應式非阻塞IO與基礎用法Webclient
- 精講RestTemplate第4篇-POST請求方法使用詳解REST
- 天貓精靈的自定義語音技能建立流程
- iOS自定義控制元件:精簡的底部彈框iOS控制元件
- Fedora 16自定義開機執行指令碼講解指令碼
- CSS人人都能寫自定義Checkbox(+1白話講解)CSS
- 精講響應式WebClient第5篇-請求超時設定與異常處理Webclient
- 精講響應式WebClient第2篇-GET請求阻塞與非阻塞呼叫方法詳解Webclient
- spark:自定義分割槽,自定義排序,spark與jdbc,廣播變數等Spark排序JDBC變數
- Synchronized 精講synchronized
- 第09講:Flink 狀態與容錯
- 精講RestTemplate第9篇-如何通過HTTP Basic Auth認證RESTHTTP
- 精講RestTemplate第3篇-GET請求使用方法詳解REST
- 精講響應式WebClient第3篇-POST、DELETE、PUT方法使用Webclientdelete
- matlab自定義函式建立與使用Matlab函式
- PHP 函式庫精講之類與物件PHP函式物件
- 精講Redis服務架構分析與搭建Redis架構
- 瘋狂Android講義(第3版) 李剛著PDF版Android
- 精講RestTemplate第10篇-使用代理作為跳板傳送請求REST
- 精講RestTemplate第5篇-DELETE、PUT等請求方法使用詳解RESTdelete