Jackson精解第4篇-@JacksonInject與@JsonAlias注解


Jackson是Spring Boot(SpringBoot)默認的JSON數據處理框架,但是其並不依賴於任何的Spring 庫。有的小伙伴以為Jackson只能在Spring框架內使用,其實不是的,沒有這種限制。它提供了很多的JSON數據處理方法、注解,也包括流式API、樹模型、數據綁定,以及復雜數據類型轉換等功能。它雖然簡單易用,但絕對不是小玩具,更多的內容我會寫成一個系列,5-10篇文章,請您繼續關注我。

本節繼續為大家介紹在JSON反序列化過程中,如何使用@JacksonInject注解和@JsonAlias注解

一、@JacksonInject注解

在使用JSON格式進行反序列化的時候,我們經常有這樣一些需求。我們從客戶端或者其他渠道獲取了一個JSON格式的數據對象,該對象包含若干個屬性。但是我們在將JSON字符串反序列化的時候,需要給它加上一些默認數據,比如:

  • responseTime數據響應時間,賦值為當前時間即可;
  • 數據反序列化的操作人,賦值為系統當前用戶等

客戶端返回給我們的數據本身不會攜帶這些附加信息,這個時候我們就可以使用JacksonInject注解,在JSON字符串反序列化為對象的時候,加上這些附加信息。下面是JacksonInject使用方法

@Data
public class PlayerStar {

  private String name;
  private Integer age;
  private String[] hobbies;    //業余愛好,數組
  private List<String> friends;   //  朋友
  private Map<String, BigDecimal> salary; //年收入 Map

  @JacksonInject("responseTime")      //注意這里
  private LocalDateTime responseTime;
}

我們來測試一下反序列化的過程,需要注意的是下文中的jsonInString中並不攜帶responseTime信息,是我們自己在反序列化的時候注入到java對象中的。

@Test
void testJSON2Object() throws IOException {
  //為responseTime賦值為當前值
  InjectableValues.Std iv = new InjectableValues.Std();
  iv.addValue("responseTime", LocalDateTime.now());

  ObjectMapper mapper = new ObjectMapper();
  mapper.setInjectableValues(iv);       //將可插入值,在反序列化過程中賦值給對象
  
  //將JSON字符串反序列化為java對象
  String jsonInString = "{\"name\":\"喬丹\",\"age\":45,\"hobbies\":[\"高爾夫球\",\"棒球\"]}";
  PlayerStar jordan = mapper.readValue(jsonInString, PlayerStar.class);

  System.out.println(jordan);

}

最終的反序列化結果,java 對象的toString()方法輸出結果如下,可以看到多出一個responseTime賦值屬性,值為當前時間

PlayerStar(name=喬丹, age=45, hobbies=[高爾夫球, 棒球], friends=null, salary=null, responseTime=2020-09-22T06:41:09.192)

二、按照數據類型type進行數據注入

在上文的代碼中,JSON字符串反序列化為對象,使用的是屬性id的方法進行注入的

  @JacksonInject("responseTime")      //注意這里responseTime為屬性id
  private LocalDateTime responseTime;
  InjectableValues.Std iv = new InjectableValues.Std();
  iv.addValue("responseTime", LocalDateTime.now());  //注意這里responseTime為屬性id,而這要統一

除了可以按照屬性id進行數據的注入,還可以使用java type數據類型進行數據注入。這種方法在一個java 類中,多個成員變量數據類型重復的時候,比如定義多個LocalDateTime成員變量,用起來就不太方便了。所以還是建議大家使用屬性id的方法進行注入數據注入。

  @JacksonInject
  private LocalDateTime responseTime;
  InjectableValues.Std iv = new InjectableValues.Std();
  iv.addValue(LocalDateTime.class, LocalDateTime.now());  //注意這里LocalDateTime.class

三、 @JsonAlias注解

當我們在開發過程中,可能在v1.0的版本中我們定義的PlayerStar類(上文)包含name屬性,但是我們用着用着發現name這個單詞太通用了,在很多的地方都是系統關鍵字;我們希望在v2.0版本中,給這個成員變量換一個名字,叫做starName,或者playerName。但是我們不希望用戶廢棄v1.0的接口。
也就是說我們希望做到多版本兼容,客戶端傳送過來的JSON字符串,可以是name、可以是playerName、可以是starName。我們該怎么做?答案是使用@JsonAlias注解

@Data
public class PlayerStar {

  @JsonAlias({"starName", "playerName" })
  private String name;

下面三種JSON格式數據都可以被正確的反序列化為PlayerStar對象,並為name成員變量賦值

String jsonInString = "{\"name\":\"喬丹\",\"age\":45,\"hobbies\":[\"高爾夫球\",\"棒球\"]}";
String jsonInString = "{\"starName\":\"喬丹\",\"age\":45,\"hobbies\":[\"高爾夫球\",\"棒球\"]}";
String jsonInString = "{\"playerName\":\"喬丹\",\"age\":45,\"hobbies\":[\"高爾夫球\",\"棒球\"]}";

歡迎關注我的博客,里面有很多精品合集

  • 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM