1. 概述
本教程將演示如何使用 Jackson 2.x 在將對象序列化為 JSON 時忽略某些字段。
這在 Jackson 的默認值不足時非常有用,我們需要精確控制哪些屬性被序列化為 JSON — 並且有多種方法可以忽略屬性。
要深入瞭解並學習我們可以使用 Jackson 做其他酷的事情,請訪問主 Jackson 教程。
2. 忽略類級別字段
我們可以忽略類級別的特定字段,使用 JsonIgnoreProperties 註解並指定字段名稱:@JsonIgnoreProperties(value = { "intValue" })
public class MyDto {
private String stringValue;
private int intValue;
private boolean booleanValue;
public MyDto() {
super();
}
// 標準的 setter 和 getter 方法未顯示
}
現在我們可以測試,在對象寫入 JSON 後,該字段確實不在輸出中:
@Test
public void givenFieldIsIgnoredByName_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, not(containsString("intValue")));
}
3. 忽略字段級別字段
我們也可以通過在字段級別直接使用 @JsonIgnore 註解來忽略字段:
public class MyDto {
private String stringValue;
@JsonIgnore
private int intValue;
private boolean booleanValue;
public MyDto() {
super();
}
// 標準的 setter 和 getter 方法未顯示
}
現在我們可以測試 intValue 字段確實不在序列化的 JSON 輸出中:
@Test
public void givenFieldIsIgnoredDirectly_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, not(containsString("intValue")));
}
4. 忽略所有類型字段
最後,我們可以使用 @JsonIgnoreType 註解忽略指定類型的所有字段。如果控制了字段類型,則可以直接對類進行註解:@JsonIgnoreType
public class SomeType { ... }
然而,在大多數情況下,我們無法控制類本身。在這種情況下,我們可以充分利用 Jackson 混合器。
首先,我們為要忽略和註解的類型定義一個 MixIn,並使用 @JsonIgnoreType 註解標記它:
@JsonIgnoreType
public class MyMixInForIgnoreType {}
然後,我們註冊該混合器以替換(並忽略)所有 String[] 類型在序列化過程中:
mapper.addMixInAnnotations(String[].class, MyMixInForIgnoreType.class);
此時,所有 String 數組將被忽略,而不是序列化為 JSON:
@Test
public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(String[].class, MyMixInForIgnoreType.class);
MyDtoWithSpecialField dtoObject = new MyDtoWithSpecialField();
dtoObject.setBooleanValue(true);
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, containsString("intValue"));
assertThat(dtoAsString, containsString("booleanValue"));
assertThat(dtoAsString, not(containsString("stringValue")));
}
以下是我們的 DTO:
public class MyDtoWithSpecialField {
private String[] stringValue;
private int intValue;
private boolean booleanValue;
}
注意:自版本 2.5 版本以來,似乎我們無法使用此方法忽略原始數據類型,但我們可以用於自定義數據類型和數組。
5. 忽略使用過濾器字段
最後,我們還可以使用過濾器忽略 Jackson 中的特定字段。首先,我們需要在 Java 對象上定義過濾器:
@JsonFilter("myFilter")
public class MyDtoWithFilter { ... }
然後,我們定義一個簡單的過濾器,忽略 intValue 字段:
SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter
.serializeAllExcept("intValue");
FilterProvider filters = new SimpleFilterProvider()
.addFilter("myFilter", theFilter);
現在,我們可以序列化對象並確保 intValue 字段不在 JSON 輸出中:
@Test
public final void givenTypeHasFilterThatIgnoresFieldByName_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter
.serializeAllExcept("intValue");
FilterProvider filters = new SimpleFilterProvider()
.addFilter("myFilter", theFilter);
MyDtoWithFilter dtoObject = new MyDtoWithFilter();
String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);
assertThat(dtoAsString, not(containsString("intValue")));
assertThat(dtoAsString, containsString("booleanValue"));
assertThat(dtoAsString, containsString("stringValue"));
System.out.println(dtoAsString);
}
6. 結論
本文介紹瞭如何忽略序列化過程中的字段。我們首先通過名稱進行忽略,然後直接忽略,最後使用 MixIns 忽略整個 Java 類型,並使用過濾器對輸出進行更精細的控制。