
Jackson是Spring Boot(SpringBoot)默認的JSON資料處理框架,但是其并不依賴于任何的Spring 庫,有的小伙伴以為Jackson只能在Spring框架內使用,其實不是的,沒有這種限制,它提供了很多的JSON資料處理方法、注解,也包括流式API、樹模型、資料系結,以及復雜資料型別轉換等功能,它雖然簡單易用,但絕對不是小玩具,更多的內容我會寫成一個系列,5-10篇文章,請您繼續關注我,
- 《序列化與反序列化核心用法-JSON框架Jackson精解第1篇》
- 《特殊資料格式處理-JSON框架Jackson精解第2篇》
- 《屬性序列化自定義排序與字母表排序-JSON框架Jackson精解第3篇》
- 《@JacksonInject與@JsonAlias注解-JSON框架Jackson精解第4篇》
- 《@JsonCreator自定義反序列化函式-JSON框架Jackson精解第5篇》
本節繼續為大家介紹在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;
執行之后的序列化和反序列化結果,和方法一、方法二自定義的實作效果是一樣的,
歡迎關注我的博客,里面有很多精品合集
- 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客,
覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! ,另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注,
- 《手摸手教你學Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《實戰前后端分離RBAC權限管理系統》
- 《實戰SpringCloud微服務從青銅到王者》
- 《VUE深入淺出系列》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/118164.html
標籤:Java
