歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類匯總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;
系列文章匯總
- jackson學習之一:基本資訊
- jackson學習之二:jackson-core
- jackson學習之三:常用API操作
- jackson學習之四:WRAP_ROOT_VALUE(root物件)
- jackson學習之五:JsonInclude注解
- jackson學習之六:常用類注解
- jackson學習之七:常用Field注解
- jackson學習之八:常用方法注解
- jackson學習之九:springboot整合(組態檔)
- jackson學習之十(終篇):springboot整合(配置類)
本篇概覽
- 本文是《jackson學習》系列第五篇,來熟悉一個常用的注解JsonInclude,該注解的僅在序列化操作時有用,用于控制方法、屬性等是否應該被序列化;
- 之所以用單獨的一篇來寫JsonInclude注解,是因為該注解的值有多種,每種都有不同效果,最好的學習方法就是編碼實戰;
- 先對注解的所有取值做個簡介:
ALWAYS // 默認策略,任何情況都執行序列化
NON_NULL // 非空
NON_ABSENT // null的不會序列化,但如果型別是AtomicReference,依然會被序列化
NON_EMPTY // null、集合陣列等沒有內容、空字串等,都不會被序列化
NON_DEFAULT // 如果欄位是默認值,就不會被序列化
CUSTOM // 此時要指定valueFilter屬性,該屬性對應一個類,用來自定義判斷被JsonInclude修飾的欄位是否序列化
USE_DEFAULTS // 當JsonInclude在類和屬性上都有時,優先使用屬性上的注解,此時如果在序列化的get方法上使用了JsonInclude,并設定為USE_DEFAULTS,就會使用類注解的設定
原始碼下載
- 如果您不想編碼,可以在GitHub下載所有原始碼,地址和鏈接資訊如下表所示(https://github.com/zq2599/blog_demos):
| 名稱 | 鏈接 | 備注 |
|---|---|---|
| 專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
| git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 |
| git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
- 這個git專案中有多個檔案夾,本章的應用在jacksondemo檔案夾下,如下圖紅框所示:

- jacksondemo是父子結構的工程,本篇的代碼在annotation子工程中,里面的jsoninclude這個package下,如下圖:

- 接下來逐個學習這些屬性的效果;
ALWAYS
ALWAYS表示全部序列化,如下圖,null和空字串都會序列化:

NON_NULL
NON_NULL好理解,就是值為null就不序列化:

NON_ABSENT
- NON_ABSENT略為復雜,當實體化的物件有Optional或AtomicReference型別的成員變數時,如果Optional參考的實體為空,用NON_ABSENT能使該欄位不做序列化;
- Optional是java用來優雅處理空指標的一個特性,本文中不做過多說明,請您自行查閱相關檔案;
- 要讓Jackson支持Optional特性,必須做兩件事,首先是在pom.xml中添加以下依賴:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.11.0</version>
</dependency>
- 其次是代碼中執行以下設定:
mapper.registerModule(new Jdk8Module());
- 咱們先看看設定成NON_NULL時jackson對Optional和AtomicReference的處理,下面的代碼中,Optional和AtomicReference的參考都是空,但還是被序列化出來了:

- 代碼不變,將NON_NULL改為NON_ABSENT試試,如下圖,可見field2和field3都沒有序列化了:

小結NON_ABSENT的效果:
a. 自身為null的欄位不會被序列化;
b. Optional型別的欄位,如果參考值為null,該欄位不會被序列化;
c. AtomicReference型別的欄位,如果參考值為null,該欄位不會被序列化;
NON_EMPTY
NON_EMPTY好理解,以下情況都不會被序列化:
- null
- 空字串
- 空集合
- 空陣列
- Optional型別的,其參考為空
- AtomicReference型別的,其參考為空
- 演示代碼和結果如下圖,可見上述場景全部沒有被序列化:

NON_DEFAULT
- 設定為NON_DEFAULT后,對保持默認值的欄位不做序列化,如下圖:

CUSTOM
- 相對其他型別,CUSTOM略為復雜,這個值要配合valueFilter屬性一起使用;
- 如下所示,JsonInclude的value等于CUSTOM時,在序列化的時候會執行CustomFilter的equals方法,該方法的入參就是field0的值,如果equals方法回傳true,field0就不會被序列化,如果equals方法回傳false時field0才會被序列化
@JsonInclude(value = https://www.cnblogs.com/bolingcavalry/p/JsonInclude.Include.CUSTOM,
valueFilter = CustomFilter.class)
private String field0;
- 來看看CustomFilter類的代碼,如下所示,只有equals方法,可見:null、非字串、長度大于2這三種情況都回傳true,也就是說這三種情況下都不會被序列化:
static class CustomFilter {
@Override
public boolean equals(Object obj) {
// null,或者不是字串就回傳true,意味著不被序列化
if(null==obj || !(obj instanceof String)) {
return true;
}
// 長度大于2就回傳true,意味著不被序列化
return ((String) obj).length() > 2;
}
}
- 下面貼出完整代碼和結果,您就一目了然了:

- 再次強調:valueFilter的equals方法回傳true,意味著該欄位不會被序列化!!!
USE_DEFAULTS
USE_DEFAULTS的用法也有點繞,咱們通過對比的方法來學習;
- 代碼如下所示,在類和成員變數上都有JsonInclude注解,序列化field0的時候,是哪個注解生效呢?:
@JsonInclude(JsonInclude.Include.NON_EMPTY)
static class Test {
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<String> field0;
public List<String> getField0() { return field0; }
public void setField0(List<String> field0) { this.field0 = field0; }
}
- 把field0設定為空集合,運行代碼試試,如果類上的注解生效,那么field0就不會被序列化(NON_EMPTY會過濾掉空集合),如果成員變數上的注解生效,field0就會被序列化(NON_NULL只過濾null,空集合不是null),執行結果如下圖,可見是成員變數上的注解生效了:

- 接下來保持上述代碼不變,僅在getField0方法上添加JsonInclude注釋,值是USE_DEFAULTS,這樣在序列化程序中,呼叫getField0方法時,就用類注解JsonInclude的值了,即NON_EMPTY:
@JsonInclude(JsonInclude.Include.USE_DEFAULTS)
public List<String> getField0() {
return field0;
}
- 執行修改后的代碼,如下圖所示,此時用的成員變數field0上的注解就不生效了,而是類注解生效,導致空集合不被序列化:

小結USE_DEFAULTS的作用如下:
a. 類注解和成員變數注解同時存在時,以成員變數注解為準;
b. 如果對應的get方法也使用了JsonInclude注解,并且值是USE_DEFAULTS,此時以類注解為準;
至此,JsonInclude注解的學習和實戰就完成了,希望本文能給您提供參考,助您熟練使用注解來指定更精確的序列化過濾策略;
你不孤單,欣宸原創一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 資料庫+中間件系列
- DevOps系列
歡迎關注公眾號:程式員欣宸
微信搜索「程式員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/255819.html
標籤:Java
