jackson學習之五:JsonInclude註解

歡迎訪問我的GitHub

//github.com/zq2599/blog_demos

內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

系列文章匯總

本篇概覽

  1. 本文是《jackson學習》系列第五篇,來熟悉一個常用的註解JsonInclude,該註解的僅在序列化操作時有用,用於控制方法、屬性等是否應該被序列化;
  2. 之所以用單獨的一篇來寫JsonInclude註解,是因為該註解的值有多種,每種都有不同效果,最好的學習方法就是編碼實戰;
  3. 先對註解的所有取值做個簡介:
ALWAYS // 默認策略,任何情況都執行序列化
NON_NULL // 非空
NON_ABSENT // null的不會序列化,但如果類型是AtomicReference,依然會被序列化
NON_EMPTY // null、集合數組等沒有內容、空字元串等,都不會被序列化
NON_DEFAULT // 如果欄位是默認值,就不會被序列化
CUSTOM // 此時要指定valueFilter屬性,該屬性對應一個類,用來自定義判斷被JsonInclude修飾的欄位是否序列化
USE_DEFAULTS // 當JsonInclude在類和屬性上都有時,優先使用屬性上的註解,此時如果在序列化的get方法上使用了JsonInclude,並設置為USE_DEFAULTS,就會使用類註解的設置  

源碼下載

  1. 如果您不想編碼,可以在GitHub下載所有源碼,地址和鏈接資訊如下表所示(//github.com/zq2599/blog_demos):
名稱 鏈接 備註
項目主頁 //github.com/zq2599/blog_demos 該項目在GitHub上的主頁
git倉庫地址(https) //github.com/zq2599/blog_demos.git 該項目源碼的倉庫地址,https協議
git倉庫地址(ssh) [email protected]:zq2599/blog_demos.git 該項目源碼的倉庫地址,ssh協議
  1. 這個git項目中有多個文件夾,本章的應用在jacksondemo文件夾下,如下圖紅框所示:

在這裡插入圖片描述

  1. jacksondemo是父子結構的工程,本篇的程式碼在annotation子工程中,裡面的jsoninclude這個package下,如下圖:

在這裡插入圖片描述

  • 接下來逐個學習這些屬性的效果;

ALWAYS

ALWAYS表示全部序列化,如下圖,null和空字元串都會序列化:

在這裡插入圖片描述

NON_NULL

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

在這裡插入圖片描述

NON_ABSENT

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

在這裡插入圖片描述

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

在這裡插入圖片描述

小結NON_ABSENT的效果:
a. 自身為null的欄位不會被序列化;
b. Optional類型的欄位,如果引用值為null,該欄位不會被序列化;
c. AtomicReference類型的欄位,如果引用值為null,該欄位不會被序列化;

NON_EMPTY

NON_EMPTY好理解,以下情況都不會被序列化:

  1. null
  2. 空字元串
  3. 空集合
  4. 空數組
  5. Optional類型的,其引用為空
  6. AtomicReference類型的,其引用為空
  7. 演示程式碼和結果如下圖,可見上述場景全部沒有被序列化:

在這裡插入圖片描述

NON_DEFAULT

  1. 設置為NON_DEFAULT後,對保持默認值的欄位不做序列化,如下圖:

在這裡插入圖片描述

CUSTOM

  1. 相對其他類型,CUSTOM略為複雜,這個值要配合valueFilter屬性一起使用;
  2. 如下所示,JsonInclude的value等於CUSTOM時,在序列化的時候會執行CustomFilter的equals方法,該方法的入參就是field0的值,如果equals方法返回true,field0就不會被序列化,如果equals方法返回false時field0才會被序列化
@JsonInclude(value = JsonInclude.Include.CUSTOM, 
                valueFilter = CustomFilter.class)
        private String field0;
  1. 來看看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;
        }
    }
  1. 下面貼出完整程式碼和結果,您就一目了然了:

在這裡插入圖片描述

  • 再次強調:valueFilter的equals方法返回true,意味著該欄位不會被序列化!!!

USE_DEFAULTS

USE_DEFAULTS的用法也有點繞,咱們通過對比的方法來學習;

  1. 程式碼如下所示,在類和成員變數上都有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; }
    }
  1. 把field0設置為空集合,運行程式碼試試,如果類上的註解生效,那麼field0就不會被序列化(NON_EMPTY會過濾掉空集合),如果成員變數上的註解生效,field0就會被序列化(NON_NULL只過濾null,空集合不是null),執行結果如下圖,可見是成員變數上的註解生效了:

在這裡插入圖片描述

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

在這裡插入圖片描述
小結USE_DEFAULTS的作用如下:
a. 類註解和成員變數註解同時存在時,以成員變數註解為準;
b. 如果對應的get方法也使用了JsonInclude註解,並且值是USE_DEFAULTS,此時以類註解為準;

至此,JsonInclude註解的學習和實戰就完成了,希望本文能給您提供參考,助您熟練使用註解來指定更精確的序列化過濾策略;

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 資料庫+中間件系列
  6. DevOps系列

歡迎關注公眾號:程式設計師欣宸

微信搜索「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界…
//github.com/zq2599/blog_demos