溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何自定義JsonSerialize以及Deserialize實現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換

發(fā)布時間:2021-12-13 21:18:16 來源:億速云 閱讀:293 作者:柒染 欄目:大數(shù)據(jù)

如何自定義JsonSerialize以及Deserialize實現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

一、LocalDateTime反序列化異常

首先我們定義一個java POJO實體類,其中關(guān)鍵的成員變量時birthDate,我們沒有采用Date數(shù)據(jù)類型,而是采用了Java8 新的日期類型LocalDateTime ,使用LocalDateTime 的好處我就不多說了,有很多的文章解釋說明。我們把精力放回到Jackson的JSON格式序列化與反序列化內(nèi)容上來。

[@Data](https://my.oschina.net/difrik)
public class PlayerStar4 {
  private String name; //姓名
  private LocalDateTime birthDate; //出生日期
}

下面的代碼,我們首先定義了一個PlayerStar4類的對象player,然后

  • 使用writeValueAsString方法將player對象序列化為JSON字符串jsonString

  • 然后使用readValue方法將JSON字符串jsonString ,反序列化為PlayerStar4類的對象

[@Test](https://my.oschina.net/azibug)
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 的過程被正常執(zhí)行了,但是LocalDateTime序列化之后的結(jié)果,是圖中”黃框中的黃框“內(nèi)容。

  • 將JSON字符串反序列化的過程報錯了,因為Jackson默認(rèn)情況下,根本不認(rèn)識圖中”黃框中的黃框“內(nèi)容這種LocalDateTime序列化之后的JSON字符串?dāng)?shù)據(jù)結(jié)構(gòu)。無法把它反序列化為java對象。

如何自定義JsonSerialize以及Deserialize實現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換

怎么辦?我們需要自定義序列化及反序列化類型轉(zhuǎn)換器,有兩種方法

  • 繼承StdConverter類,自定義實現(xiàn)String與LocalDateTime相互轉(zhuǎn)換

  • 繼承JsonSerializer和JsonDeserializer類,自定義實現(xiàn)String與LocalDateTime相互轉(zhuǎn)換

二、方法一:繼承StdConverter類

繼承StdConverter類,將LocalDateTime序列化為String數(shù)據(jù)類型

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數(shù)據(jù)類型反序列化為LocalDateTime

public class StringToLocalDatetimeConverter extends StdConverter<String, LocalDateTime> {
  @Override
  public LocalDateTime convert(String value) {
      return LocalDateTime.parse(value, LocalDateTimeToStringConverter.DATE_FORMATTER);
  }
}

自定義的轉(zhuǎn)換器完成之后,我們就可以在對應(yīng)的成員變量上,使用@JsonSerialize指定序列化轉(zhuǎn)換器,@JsonDeserialize指定反序列化轉(zhuǎn)換器。

  @JsonSerialize(converter = LocalDateTimeToStringConverter.class)
  @JsonDeserialize(converter = StringToLocalDatetimeConverter.class)
  private LocalDateTime birthDate;

然后調(diào)用第一小節(jié)中的測試用例,就不會出現(xiàn)異常了??刂婆_打印輸出結(jié)果如下,第一行是序列化結(jié)果JSON格式字符串,第二行是Java 對象的toString()方法的打印結(jié)果。

{"name":"curry","birthDate":"1986-4-5 12:50:00"}
PlayerStar4(name=curry, birthDate=1986-04-05T12:50)

三、方法二:繼承JsonSerializer和JsonDeserializer類

繼承JsonSerializer<LocalDateTime>類,將LocalDateTime序列化為String數(shù)據(jù)類型

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數(shù)據(jù)類型反序列化為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);
  }
}

四、如果上面的你都沒看懂

對于相對小白的讀者,上面的自定義序列化及反序列化轉(zhuǎn)換過程你都沒懂,對于LocalDateTime的異常你也不要慌,Jackson已經(jīng)給出了解決方案。

需要特別和大家強調(diào)的是LocalDateTimeSerializer和LocalDateTimeDeserializer其實并不需要我們自己去定義,因為Jackson已經(jīng)幫我們定義好了。 之所以我還做了自定義的實現(xiàn)的介紹,是因為要為大家講解這個自定義序列化和反序列化類型轉(zhuǎn)換的實現(xiàn)過程,以后你再遇到其他的特殊的數(shù)據(jù)類型轉(zhuǎn)換,或者LocalDateTime類型的特殊日期格式等,都可以自己來定義JsonSerialize和JsonDeserialize來實現(xiàn)數(shù)據(jù)類型的轉(zhuǎn)換。

下面的這兩個類就是Jackson已經(jīng)幫我們定義好的LocalDateTimeSerializer和LocalDateTimeDeserializer。

import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;

使用方法是在對應(yīng)的成員變量上,使用@JsonSerialize指定序列化轉(zhuǎn)換器,@JsonDeserialize指定反序列化轉(zhuǎn)換器。

@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime birthDate;

執(zhí)行之后的序列化和反序列化結(jié)果,和方法一、方法二自定義的實現(xiàn)效果是一樣的。

看完上述內(nèi)容,你們掌握如何自定義JsonSerialize以及Deserialize實現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI