Java開發中POJO和JSON互轉時如何忽略隱藏欄位

碼農小胖哥發表於2021-02-03

1. 前言

Java開發中有時候某些敏感資訊我們需要遮蔽掉,不能被消費這些資料的客戶端知道。通常情況下我們會將其設定為null或者空字元 "",其實還有其它辦法,如果你使用了Jackson的話。接下來我將以一個實際場景來告訴你可以怎麼做。

2. Jackson如何忽略欄位

這裡都以JSON序列化為例。假如我們在業務中需要返回使用者資訊,已有的POJO是這樣的:

import lombok.Data;

/**
 * @author felord.cn
 */
@Data
public class UserInfo {
    /**
     * userid
     */
    private String userId;
    /**
     * 使用者名稱
     */
    private String username;
    /**
     * 金鑰串
     */
    private String secret;
    /**
     * 地址資訊
     */
    private String address;
}

業務場景:第三方通過使用者的userId來獲取使用者的資訊,但是金鑰串secret顯然不能讓第三方知道,通常最容易想到的方法是將secret欄位設定為null或者""。如果業務需要批量提供使用者資訊,即List<UserInfo>,我們總不能每次都要遍歷一遍吧。Spring Boot內建的Jackson可以很方便的幫我們處理這個問題。

使用@JsonIgnore註解

Jackson提供了一個@JsonIgnore註解,將它標記到需要被忽略的欄位上或者對應的getter方法或者setter方法上就可以實現對該欄位的遮蔽。就像下面這樣標記:

     @JsonIgnore
    private String secret;
   // 對應json 樣例  {"userId":"100000","username":"felord.cn","address":"cn"}

無論是序列化(將POJO轉為JSON)還是反序列化((將JSON轉為POJO),secret都會被忽略。

使用@JsonIgnoreProperties註解

這個註解比@JsonIgnore更加強大一些,通常該註解標記到POJO之上,它有更多的能力:

  • 忽略多個欄位,配置value屬性即可。
  • 忽略未知的屬性,配置ignoreUnknowntrue,預設不忽略。
  • 允許忽略欄位被序列化,配置allowGetterstrue,序列化的時候不會被忽略。
  • 允許忽略欄位被反序列化,配置allowSetterstrue,反序列化的時候不會被忽略。

例如我們要忽略UserInfo中的secretaddress,我們可以這樣配置:

@JsonIgnoreProperties({"secret", "address"})

使用@JsonProperty註解

需要Jackson版本不低於2.6

這個註解出鏡率還是非常高的,通常為了給JSON的欄位起別名或者設定預設值使用。比如UserInfo中的userId想對應JSON中的user_id,我們可以:

@JsonProperty(value = "user_id")
private String userId;

在2.6版本以後,這個註解也能實現忽略欄位的作用。它有個access屬性,用來指定在序列化(“讀取”)和反序列化(“寫”)期間訪問許可權(這裡的讀寫是以屬性為視角)。它由列舉Access定義:

public enum Access
{
    /**
     * 無論是序列化還是反序列化都會根據配置自動的處理,預設值。
     */
    AUTO,

    /**
     * 意味著該屬性只能在進行序列化時讀取(通過“ getter”方法訪問的值,或者從欄位中讀取),而在反序列化      * 期間不能寫入(設定)。換句話說,這將反映“只讀POJO”,其中包含的值可以讀取但不能寫入。
     */
    READ_ONLY,

    /**
     * 意味著該屬性只能作為反序列化的一部分寫入(設定)(使用“ setter”方法,或分配給Field,或作為          * Creator引數傳遞),而不會被讀取(獲取)以進行序列化,即,該屬性的值不包括在序列化中。
     */
    WRITE_ONLY,

    /**
     * 可讀可寫,READ_ONLY與WRITE_ONLY的合併效果。
     */
    READ_WRITE;
}

從這個註解中我們可以知道,如果你想在POJOJSON時忽略secret欄位,就可以這麼寫:

@JsonProperty( access = JsonProperty.Access.WRITE_ONLY)
private String secret;

使用@JsonIgnoreType註解

這個註解是用來直接忽略型別的,如果上面的UserInfo是另外一個POJO的屬性,我們不希望它被序列化和反序列化,那麼就可以:

@JsonIgnoreType
public class UserInfo {
   // 省略
}

3. 總結

目前大概可知的Jackson有這麼四種的忽略屬性的方式,它們有各自的使用場景,你可以根據自己的情況選擇使用。好了今天的分享就到這裡,多多關注:碼農小胖哥,獲取更多的程式設計乾貨。

關注公眾號:Felordcn 獲取更多資訊

個人部落格:https://felord.cn

相關文章