Jackson前後端開發模式必備json利器

2023-06-02 06:00:37

前言

json是我們現代網際網路程式最常用的互動格式,是否你在工作中會遇到前端說欄位不一致需要改的需求,是否遇到過資料庫欄位名與javaBean的規範不同,是否遇到過json與javaBean相互轉換時因為需求寫的土匪程式碼,這些都可以用Jackson完成,我們經常和json打交道,而Jackson就是幫助我們更好的處理json的框架,SpringBoot預設自帶,還有一款Fastjson,阿里開源的,國內這兩種用的比較多,我選擇了Jackson,老牌穩定。
先來了解兩個概念:

  1. JSON序列化:Object -> JSONString
  2. JSON反序列化:JSONString -> Object

Jackson庫介紹

Jackson庫有兩個核心類:​ObjectMapper​​​和​​JsonNode​​。

​​ObjectMapper​​​類是Jackson庫中最重要的類,它提供了序列化和反序列化Java物件與JSON之間的轉換。​​ObjectMapper​​類的範例是執行緒安全的,可以在多執行緒環境中共用

​​JsonNode​​​類是一個抽象類,它代表了一個JSON節點。​​JsonNode​​​類有多個子類,例如​​ObjectNode​​​、​​ArrayNode​​​、​​ValueNode​​​等,分別對應JSON中的物件、陣列和值。​​JsonNode​​類提供了方便的方法來讀取JSON節點的值。

註解

註解是我們最常用的方式,直接選擇常用的開搞,全註解 http://https://www.baeldung.com/jackson-annotations

適用序列化和反序列化

@JsonProperty

@JsonProperty 序列化與反序列化別名,作用於屬性上

  • @JsonProperty.value: 要使用的名稱(別名)
  • @JsonProperty.index:要使用的物理索引,如果資料格式(JSON 除外)是基於索引的 預設值-1
  • @JsonProperty.defaultValue: 定義為後設資料的文字預設值。注意:核心資料繫結不使用這個值;它目前只暴露給擴充套件模組。
  • @JsonProperty.required: 序列化與反序列化時候屬性是否必須要有,如果為true沒有的話會丟擲異常,預設值 false

@JsonFormat

  • @JsonFormat 日期、時間、數位,序列化與反序列化
  • @JsonFormat.pattern:用於指定日期、時間、數位等的格式模式。例如,"yyyy-MM-dd" 表示日期格式為 "年-月-日"。預設為空字串 ""。
  • @JsonFormat.shape:用於指定屬性的序列化和反序列化形狀。預設為 JsonFormat.Shape.ANY。常用的取值包括:
    JsonFormat.Shape.STRING:將屬性序列化為字串。
    JsonFormat.Shape.NUMBER:將屬性序列化為數位。
    JsonFormat.Shape.ARRAY:將屬性序列化為陣列。
    JsonFormat.Shape.OBJECT:將屬性序列化為物件。
  • @JsonFormat.locale:用於指定地區(Locale),在日期、時間格式化時可能會用到。預設為 JsonFormat.DEFAULT_LOCALE,系統預設地區
  • @JsonFormat.timezone:用於指定時區,對於日期和時間的處理往往與時區有關。預設為空字串 "",系統預設時區
  • @JsonFormat.patternLocale:用於指定日期、時間格式模式的地區(Locale)。預設為 JsonFormat.DEFAULT_LOCALE,通常是 Java 虛擬機器器預設的地區(Locale)。
  • @JsonFormat.lenient:用於指定是否允許寬鬆的解析,例如接受部分格式不符合模式的輸入。預設為 false

如果將 lenient 屬性設定為 true,則在反序列化過程中可以允許一些非嚴格匹配的輸入。例如,如果輸入的日期字串為 "2021-01",它並不符合完整的 "yyyy-MM-dd" 格式,但由於 lenient 設定為 true,Jackson 可以進行寬鬆解析,將其解釋為 2021 年 1 月的某個日期(如 2021 年 1 月 1 日)。

@JsonUnwrapped

@JsonUnwrapped 序列與反序列化時物件屬性是否需要展開在父物件上,Map不適用,Map用@JsonAnyGetter
例如:

public class User {
    private String name;
    @JsonUnwrapped
    private Address address;
}
public class Address {
    private String street;
    private String city;
}

結果

{
  "name": "John",
  "street": "123 Main St",
  "city": "New York"
}

適用序列化

@JsonPropertyOrder

@JsonPropertyOrder 序列化時排列排列順序

  • @JsonProperty.value: 屬性名
  • @JsonProperty.alphabetic:是否按字母順序排列

@JsonIgnore

@JsonIgnore 序列化時忽略的屬性,作用於屬性上

@JsonIgnoreProperties

@JsonIgnoreProperties 序列化忽略的屬性集合,作用於類上

  • @JsonIgnoreProperties.value :在序列化時,忽略列出的屬性
  • @JsonIgnoreProperties.ignoreUnknown:在反序列化時,忽略沒有 getter/setter 的屬性

@JsonIgnoreType

@JsonIgnoreType 忽略註釋型別的所有屬性,作用於類上

@JsonInclude

@JsonInclude 序列化時,值為規則這個屬性隱藏,作用於類和屬性上

  • @JsonInclude.value:規則 預設值JsonInclude.Include.ALWAYS
  • @JsonInclude.content:集合型別屬性規則 預設值JsonInclude.Include.ALWAYS
    JsonInclude.Include.ALWAYS:始終包含屬性,即使屬性值為 null。
    JsonInclude.Include.NON_NULL:僅在屬性值不為 null 時才包含屬性。
    JsonInclude.Include.NON_DEFAULT:僅在屬性值與預設值不相等時才包含屬性。
    JsonInclude.Include.NON_EMPTY:僅在屬性值不為 null 且不為空(例如空字串或空集合)時才包含屬性。

@JsonAnyGetter

@JsonAnyGetter 註釋允許靈活地將Map屬性用作標準屬性平鋪在父物件上,適用序列化,作用於get方法上,返序列化用@JsonAnySetter
例如:

@Data
public class OrderDetails {
    Map<String, String> tempMap = new HashMap<String, String>(){{
        put("temp","temp");
        put("temp1","temp1");
    }};

    @JsonAnyGetter
    public Map<String, String> getTempMap() {
        return tempMap;
    }
}

結果

{
    "temp": "temp",
    "temp1": "temp1"
}

@JsonGetter

@JsonGetter 序列化時別名,作用於get方法上

@JsonView

@JsonView 序列與反序列化 分組選擇需要顯示的屬性
例子:

@Data
public class OrderDetails {
    public interface UserSimpleView {};
    public interface UserDetailView {};

    @JsonView({UserSimpleView.class,UserDetailView.class})
    String name = "yues";
    @JsonView(UserDetailView.class)
    String password = "123";
}

結果:

@JsonView(OrderDetails.UserSimpleView.class)
@RequestMapping("/add")
public Object add(@RequestBody OrderDetails orderDetails) {
//        {
//            "name": "yues"
//        }
	return orderDetails;
}
@JsonView(OrderDetails.UserDetailView.class)
@RequestMapping("/add")
public Object add(@RequestBody OrderDetails orderDetails) {
//        {
//            "name": "yues",
//            "password": "123"
//        }
	return orderDetails;
}

@JsonRootName

@JsonRootName 包一層
例子:

@Data
@JsonRootName("user")
public class OrderDetails {
    String name = "yues";
}

{
  "user":  {
     "name": "yues"
  },
}

@JsonSerialize

@JsonSerialize 自定義序列化器

  • using:指定要使用的自定義序列化器類。該引數接受一個實現了 Jackson 的 JsonSerializer 介面的類。您可以編寫自定義的序列化器類來控制屬性的序列化行為。

    值為null不會執行

  • as:在序列化過程中,指定使用的序列化器型別。預設情況下,Jackson 會根據屬性的型別來選擇合適的序列化器。使用 as 引數可以強制指定序列化器的型別,覆蓋預設的選擇。
  • keyUsing:在序列化過程中,指定用於序列化屬性鍵(如果屬性是一個 Map 或類似結構的鍵值對)的自定義序列化器。該引數接受一個實現了 Jackson 的 JsonSerializer 介面的類。
  • contentUsing:在序列化過程中,指定用於序列化屬性值(如果屬性是一個 Collection 或類似結構的集合)的自定義序列化器。該引數接受一個實現了 Jackson 的 JsonSerializer 介面的類。
  • nullsUsing:在序列化過程中,指定用於處理屬性值為 null 的自定義序列化器。該引數接受一個實現了 Jackson 的 JsonSerializer 介面的類。通過設定 nullsUsing 引數,您可以定義在屬性值為 null 時應該採取的序列化行為。

反序列化

@JsonSetter

@JsonGetter 反序列化時別名,作用於set方法上

@JsonAlias

@JsonAlias 反序列化時別名可以應用於類的屬性上且可以指定多個

@JsonDeserialize

@JsonDeserialize 自定義反序列化器

  • using:指定要使用的自定義反序列化器類。該屬性接受一個實現了 Jackson 的 JsonDeserializer 介面的類。您可以編寫自定義的反序列化器類來控制屬性的反序列化行為。
  • contentUsing:在反序列化過程中,指定用於處理屬性值(如果屬性是一個 Collection 或類似結構的集合)的自定義反序列化器。該屬性接受一個實現了 Jackson 的 JsonDeserializer 介面的類。
  • keyUsing:在反序列化過程中,指定用於處理屬性鍵(如果屬性是一個 Map 或類似結構的鍵值對)的自定義反序列化器。該屬性接受一個實現了 Jackson 的 JsonDeserializer 介面的類。
  • contentAs:在反序列化過程中,指定用於處理屬性值(如果屬性是一個 Collection 或類似結構的集合)的型別。通過設定 contentAs 屬性,您可以強制 Jackson 使用指定的型別進行屬性值的反序列化。

自定義註解

例子

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
@JsonDeserialize //自定義反序列化
@@JsonSerialize  //自定義序列化
public @interface CustomAnnotation {}

不用註解ObjectMapper物件

以上的註解都可以使用ObjectMapper物件來設定,先有ObjectMapper才有的這些註解,上面的註解都是使用ObjectMapper來完成的,在SpringBoot中我們還可以用ObjectMapper Bean來達到全域性設定,當然也可以用組態檔。在日常的開發工作中,我們經常全域性制定日期格式、駝峰_轉換等等。
這裡就不多做使用ObjectMapper來詳細說,貼一些常用的方法吧

ObjectMapper mapper = new ObjectMapper()
mapper.enable(序列化設定);
mapper.configure(反序列化設定);
// 將字串、byte[]轉換為物件 序列化
mapper.readValue(jsonString, User.class);
// 此方法更靈活,可以只將使用者感興趣的Json串資訊值提取出來 序列化
mapper.readTree(test);

// 將物件轉換為json字串 反序列化
mapper.writeValueAsString(user);
// 將物件轉換為byte 反序列化
mapper.writeValueAsBytes(user)