Jackson註解使用示例

原文地址

1 概述

在本文中,我們將深入探討Jackson註解。
我們將看到如何使用Jackson現有的註解,如何創建自定義註解以及如何禁用它們。

2 Jackson序列化註解

2.1 @JsonAnyGetter

@JsonAnyGetter註解提供了將Map字段轉換爲標準屬性的靈活性。這是一個簡單的示例– ExtendableBean實體具有name屬性和一組以K/V對形式的可擴展屬性:

public class ExtendableBean {
    public String name;
    private Map<String, String> properties;

    public ExtendableBean() {
        properties = new HashMap<String, String>();
    }

    public ExtendableBean(final String name) {
        this.name = name;
        properties = new HashMap<String, String>();
    }

    @JsonAnySetter
    public void add(final String key, final String value) {
        properties.put(key, value);
    }

    @JsonAnyGetter
    public Map<String, String> getProperties() {
        return properties;
    }
}

序列化此實體的實例時,我們將Map中的所有鍵值作爲標準的純屬性獲取,如下:

{
    "name":"My bean",
    "attr2":"val2",
    "attr1":"val1"
}

測試:

    @Test
    public void whenSerializingUsingJsonAnyGetter_thenCorrect() throws JsonProcessingException {
        final ExtendableBean bean = new ExtendableBean("My bean");
        bean.add("attr1", "val1");
        bean.add("attr2", "val2");

        String result = new ObjectMapper().writeValueAsString(bean);
        System.out.println(result);
    }

我們還可以使用啓用爲false的可選參數來禁用@JsonAnyGetter()。在這種情況下,地圖將轉換爲JSON,並在序列化後顯示在properties變量下。{"name":"My bean","properties":{"attr2":"val2","attr1":"val1"}}

2.2 @JsonGetter

@JsonGetter註解是@JsonProperty註解的替代方法,用於將方法標記爲getter方法。

在以下示例中,我們將方法getTheName()指定爲MyBean實體的name屬性的getter方法:

public class MyBean {
    private int id;
    private String name;

    public MyBean() {

    }

    public MyBean(final int id, final String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @JsonGetter("name")
    public String getTheName() {
        return name;
    }

    @JsonSetter("name")
    public void setTheName(String name) {
        this.name = name;
    }
}

測試:

    @Test
    public void whenSerializingUsingJsonGetter_thenCorrect()
            throws JsonProcessingException {

        MyBean bean = new MyBean(1, "My bean");

        String result = new ObjectMapper().writeValueAsString(bean);

        System.out.println(result);
    }
// {"id":1,"name":"My bean"}

因爲這裏name屬性是私有的,且get和set方法名不是使用get/set+屬性名。而jackson在序列化的時候,如果是私有屬性會調用它的get方法,默認的get方法名就是get+屬性名。如果不使用@JsonGetter註解指定,jackson會認爲theName是一個屬性。輸出如下:
{"id":1,"theName":"My bean"}

2.3 @JsonPropertyOrder

我們可以使用@JsonPropertyOrder註解指定序列化屬性的順序。讓我們爲MyBean實體的屬性設置自定義順序:

@JsonPropertyOrder({ "name", "id" })
public class MyBean {
    public int id;
    public String name;
}

測試輸出如下:
{"name":"My bean","id":1}
我們還可以使用@JsonPropertyOrder(alphabetic = true)按字母順序對屬性進行排序。在這種情況下,序列化的輸出將是:{"id":1,"name":"My bean"}

2.4 @JsonRawValue

@JsonRawValue註解可以使Jackson完全按原樣序列化屬性。

在以下示例中,我們使用@JsonRawValue嵌入一些自定義JSON作爲實體的值:

public class RawBean {
    public String name;

    @JsonRawValue
    public String json;

    public RawBean() {}

    public RawBean(final String name, final String json) {
        this.name = name;
        this.json = json;
    }
}

測試:

    @Test
    public void whenSerializingUsingJsonRawValue_thenCorrect() throws JsonProcessingException {
        final RawBean bean = new RawBean("My bean", "{\"attr\":false}");

        final String result = new ObjectMapper().writeValueAsString(bean);

        System.out.println(result);
    }
// {"name":"My bean","json":{"attr":false}}

// 如果不加@JsonRawValue註解;輸出爲:{"name":"My bean","json":"{\"attr\":false}"}

我們還可以使用可選的布爾參數值(value)來定義此註解是否起作用。

2.5 @JsonValue

@JsonValue註解的作用是告訴jackson序列化類實例時使用它標註的的單個方法。

例如,在一個枚舉中,我們用@JsonValue註釋getName,以便任何這樣的實體都通過其名稱序列化:

public enum TypeEnumWithValue {
    TYPE1(1, "Type A"),
    TYPE2(2, "Type 2");

    private Integer id;
    private String name;

    TypeEnumWithValue(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @JsonValue
    public String getName() {
        return name;
    }
}

測試:

    @Test
    public void whenSerializingUsingJsonValue_thenCorrect()
            throws JsonParseException, IOException {

        String enumAsString = new ObjectMapper()
                .writeValueAsString(TypeEnumWithValue.TYPE1);

        System.out.println(enumAsString);

    }
// "Type A"

如果不使用@JsonValue標記,枚舉序列化出來的是"TYPE1"

2.6 @JsonRootName

@JsonRootName的作用可以理解爲,在序列化好的json串外面再包裹一層。
假設之前我們的序列化之後是這樣的:

{
    "id": 1,
    "name": "John"
}

使用@JsonRootName包裹一層會變成這樣

{
    "user": {
        "id": 1,
        "name": "John"
    }
}

看一下如何使用:

@JsonRootName(value = "user")
public class UserWithRoot {
    public int id;
    public String name;
}

從Jackson 2.4開始,新的可選參數名稱空間可用於XML等數據格式。如果添加它,它將成爲完全限定名稱的一部分:

@JsonRootName(value = "user", namespace="users")
public class UserWithRootNamespace {
    public int id;
    public String name;
 
    // ...
}

xml效果是這樣的

<user xmlns="users">
    <id xmlns="">1</id>
    <name xmlns="">John</name>
    <items xmlns=""/>
</user>

2.7 @JsonSerialize

@JsonSerialize表示在序列化實體時要使用的自定義序列化程序。

讓我們看一個簡單的例子。我們將使用@JsonSerialize通過CustomDateSerializer來序列化eventDate屬性:

public class EventWithSerializer {
    public String name;
 
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}

這是簡單的自定義Jackson序列化器:

public class CustomDateSerializer extends StdSerializer<Date> {
    private static final long serialVersionUID = -2894356342227378312L;

    private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");

    public CustomDateSerializer() {
        this(null);
    }

    public CustomDateSerializer(final Class<Date> t) {
        super(t);
    }

    @Override
    public void serialize(Date date,
                          JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(formatter.format(date));
    }
}

讓我們測試下:

    @Test
    public void whenSerializingUsingJsonSerialize_thenCorrect()
            throws JsonProcessingException {

        Date date = new Date();
        EventWithSerializer event = new EventWithSerializer("party", date);

        String result = new ObjectMapper().writeValueAsString(event);
        System.out.println(result);
    }
// {"name":"party","eventDate":"24-02-2020 02:34:26"}

3 Jackson反序列化註解

3.1 @JsonCreator

我們可以使用@JsonCreator註解來調整反序列化中使用的構造函數/工廠。

當我們需要反序列化某些與我們需要獲取的目標實體不完全匹配的JSON時,這非常有用。
讓我們看一個例子;假設我們需要反序列化的JSON如下:

{
    "id":1,
    "theName":"My bean"
}

但是,我們的目標實體中沒有theName字段,只有一個name字段。現在,我們不想更改實體本身,我們只需要對解組過程進行更多控制,通過使用@JsonCreator註釋構造函數並同時使用@JsonProperty註釋:

public class BeanWithCreator {
    public int id;
    public String name;
 
    @JsonCreator
    public BeanWithCreator(
      @JsonProperty("id") int id, 
      @JsonProperty("theName") String name) {
        this.id = id;
        this.name = name;
    }
}

測試

    @Test
    public void whenDeserializingUsingJsonCreator_thenCorrect()
            throws IOException {

        String json = "{\"id\":1,\"theName\":\"My bean\"}";

        BeanWithCreator bean = new ObjectMapper()
                .readerFor(BeanWithCreator.class)
                .readValue(json);
        System.out.println(bean.name);
    }
// My bean
// 如果不使用,會報錯。

3.2 @JacksonInject

@JacksonInject表示該屬性將從注入中獲取而不是從JSON數據獲取其值。

public class BeanWithInject {
    @JacksonInject
    public int id;
    public String name;

    public BeanWithInject() {

    }

    public BeanWithInject(final int id, final String name) {
        this.id = id;
        this.name = name;
    }
}

測試如下:

    @Test
    public void whenDeserializingUsingJsonInject_thenCorrect()
            throws IOException {

        String json = "{\"name\":\"My bean\"}";

        // 使用jackson的InjectableValues類進行注入
        InjectableValues inject = new InjectableValues.Std()
                .addValue(int.class, 1);

        BeanWithInject bean = new ObjectMapper()
                .reader(inject)
                .forType(BeanWithInject.class)
                .readValue(json);

        System.out.println(bean);
    }
// BeanWithInject{id=1, name='My bean'}

3.3 @JsonAnySetter

@JsonAnySetter使我們可以靈活地使用Map作爲標準屬性。反序列化時,JSON的屬性將簡單地添加到地圖中。和之前介紹的@JsonAnyGetter正好相反。

public class ExtendableBean {
    public String name;
    private Map<String, String> properties;
 
    @JsonAnySetter
    public void add(String key, String value) {
        properties.put(key, value);
    }
}

假設我們的json是這樣的:

{
    "name":"My bean",
    "attr2":"val2",
    "attr1":"val1"
}

那麼attr2attr1會注入到Map中。

3.4 @JsonSetter

和之前介紹的@JsonGetter相反,不做過多介紹。

3.5 @JsonDeserialize

這個是用來指定自定義的反序列化規則的。

讓我們來看一個例子,我們將使用@JsonDeserialize與CustomDateDeserializer反序列化eventDate屬性:

public class EventWithSerializer {
    public String name;

    @JsonDeserialize(using = CustomDateDeserializer.class)
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}

自定義的反序列化器:

public class CustomDateDeserializer extends StdDeserializer<Date> {

    private static final long serialVersionUID = -5451717385630622729L;

    private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");

    public CustomDateDeserializer() {
        this(null);
    }

    public CustomDateDeserializer(final Class<?> vc) {
        super(vc);
    }


    @Override
    public Date deserialize(JsonParser jsonParser,
                            DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        final String date = jsonParser.getText();
        try {
            return formatter.parse(date);
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }
}

測試:

    @Test
    public void whenDeserializingUsingJsonDeserialize_thenCorrect()
            throws IOException {

        String json = "{\"name\":\"party\",\"eventDate\":\"02-02-2020 02:30:00\"}";

        EventWithSerializer event = new ObjectMapper()
                .readerFor(EventWithSerializer.class)
                .readValue(json);

        System.out.println(event);
    }
// EventWithSerializer{name='party', eventDate=Sun Feb 02 02:30:00 CST 2020}

3.6 @JsonAlias

@JsonAlias在反序列化期間爲屬性定義一個或多個備用名稱。

讓我們用一個簡單的例子看看這個註解是如何工作的:

public class AliasBean {
    @JsonAlias({ "fName", "f_name" })
    private String firstName;   
    private String lastName;
}

在這裏,我們有一個POJO,我們想將JSON中的fName、f_name或firstName屬性的值反序列化到POJO的firstName變量中。
測試如下:

    @Test
    public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
        String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";

        AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);

        System.out.println(aliasBean);
    }
// AliasBean{firstName='John', lastName='Green'}

4 Jackson屬性包含註解

4.1 @JsonIgnoreProperties

@JsonIgnoreProperties是一個類級別的註解,用於標記Jackson將忽略的一個屬性或一系列屬性。

讓我們看一個簡單的示例,忽略序列化中的屬性ID:

@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
    public int id;
    public String name;
}

4.2 @JsonIgnore

@JsonIgnore批註用於在字段級別標記要忽略的屬性。

public class BeanWithIgnore {
    @JsonIgnore
    public int id;
 
    public String name;
}

4.3 @JsonIgnoreType

@JsonIgnoreType將帶註解類的所有屬性標記爲忽略。

public class User {
    public int id;
    public Name name;
 
    @JsonIgnoreType
    public static class Name {
        public String firstName;
        public String lastName;
    }
}

4.4 @JsonInclude

我們可以使用@JsonInclude排除具有empty/null/default values的屬性。

// 從序列化中排除空值:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyBean {
    public int id;
    public String name;
}

4.5 @JsonAutoDetect

@JsonAutoDetect可以覆蓋默認語義,即哪些屬性可見,哪些屬性不可見。

讓我們來看一個簡單的示例,該註解如何幫助我們讓私有屬性可序列化:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean {
    private int id;
    private String name;

    public PrivateBean() {}

    public PrivateBean(final int id, final String name) {
        this.id = id;
        this.name = name;
    }
}

測試:

    @Test
    public void whenSerializingUsingJsonAutoDetect_thenCorrect()
            throws JsonProcessingException {

        PrivateBean bean = new PrivateBean(1, "My bean");

        String result = new ObjectMapper()
                .writeValueAsString(bean);

        System.out.println(result);
    }
// {"id":1,"name":"My bean"}

這樣,私有屬性沒有get方法也可以被序列化了。

5 Jackson多態類型處理註解

接下來–讓我們看一下Jackson的多態類型處理註釋:

  • @JsonTypeInfo - 指示要在序列化中包含哪些類型信息的詳細信息
  • @JsonSubTypes - 指示帶註解類型的子類型
  • @JsonTypeName - 定義用於註解類的邏輯類型名稱

讓我們看一個複雜的示例,使用@JsonTypeInfo,@ JsonSubTypes@JsonTypeName三個註解序列化和反序列化實體Zoo

public class Zoo {

    public Animal animal;

    public Zoo() {}

    public Zoo(final Animal animal) {
        this.animal = animal;
    }


    /***********************以下是三個靜態內部類*********************/


    public static class Animal {
        public String name;

        public Animal() {}

        public Animal(final String name) {
            this.name = name;
        }
    }
    public static class Dog extends Animal {
        public double barkVolume;

        public Dog() {}

        public Dog(final String name) {
            this.name = name;
        }
    }

    public static class Cat extends Animal {
        boolean likesCream;
        public int lives;

        public Cat() {}

        public Cat(final String name) {
            this.name = name;
        }
    }
}

以上我們什麼註解都沒有加,看序列化後是什麼結果

    @Test
    public void whenSerializingPolymorphic_thenCorrect()
            throws JsonProcessingException {
        Zoo.Dog dog = new Zoo.Dog("lacy");
        Zoo zoo = new Zoo(dog);

        String result = new ObjectMapper()
                .writeValueAsString(zoo);

        System.out.println(result);
    }
// {"animal":{"name":"lacy","barkVolume":0.0}}

這樣序列化後,我們只知道是一個動物,卻不知道具體是什麼動物,下面我們就利用以上三個註解進行修飾下。

    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = Dog.class, name = "dog"),
            @JsonSubTypes.Type(value = Cat.class, name = "cat")
    })
    public static class Animal {
        public String name;

        public Animal() {}

        public Animal(final String name) {
            this.name = name;
        }
    }

    @JsonTypeName("dog")
    public static class Dog extends Animal {
        public double barkVolume;

        public Dog() {}

        public Dog(final String name) {
            this.name = name;
        }
    }

    @JsonTypeName("cat")
    public static class Cat extends Animal {
        boolean likesCream;
        public int lives;

        public Cat() {}

        public Cat(final String name) {
            this.name = name;
        }
    }

我們在Animal類上加上以上註解,再看一下序列化後的結果

{"animal":{"type":"dog","name":"lacy","barkVolume":0.0}}

我們發現爲我們多加了一個type屬性。

下面試一下反序列化

    @Test
    public void whenDeserializingPolymorphic_thenCorrect()
            throws IOException {
        String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
        // {"animal":{"name":"lacy","type":"cat","likesCream":false,"lives":2}}

        Zoo zoo = new ObjectMapper()
                .readerFor(Zoo.class)
                .readValue(json);

        assertEquals("lacy", zoo.animal.name);
        assertEquals(Zoo.Cat.class, zoo.animal.getClass());

    }
// 可以正常執行通過。

如果將 String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";改爲String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"dog\"}}";就會報錯。

6 Jackson其他註解

6.1 @JsonProperty

我們可以添加@JsonProperty註解在JSON中指示屬性名稱。可以看做是@JsonGetter和@JsonSetter的組合版

在處理非標準的getter和setter時,我們可以使用@JsonProperty來序列化/反序列化屬性名:

public class MyBean {
    public int id;
    private String name;
 
    @JsonProperty("name")
    public void setTheName(String name) {
        this.name = name;
    }
 
    @JsonProperty("name")
    public String getTheName() {
        return name;
    }
}

6.2 @JsonFormat

@JsonFormat註解指定序列化時間類型的格式。

public class EventWithFormat {
    public String name;
 
    @JsonFormat(
      shape = JsonFormat.Shape.STRING,
      pattern = "dd-MM-yyyy hh:mm:ss")
    public Date eventDate;
}

經測試,@JsonFormat對java8新增的時間類型LocalDateTime等,不適用。

6.3 @JsonUnwrapped

@JsonUnwrapped定義在序列化/反序列化時應該解包/展平的值。

public class UnwrappedUser {
    public int id;

    @JsonUnwrapped
    public Name name;

    public UnwrappedUser() {}

    public UnwrappedUser(final int id, final Name name) {
        this.id = id;
        this.name = name;
    }

    public static class Name {
        public String firstName;
        public String lastName;

        public Name() {

        }

        public Name(final String firstName, final String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }
}

序列化測試:

    @Test
    public void whenSerializingUsingJsonUnwrapped_thenCorrect()
            throws JsonProcessingException {
        UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
        UnwrappedUser user = new UnwrappedUser(1, name);

        String result = new ObjectMapper().writeValueAsString(user);

        System.out.println(result);
    }
// {"id":1,"firstName":"John","lastName":"Doe"}

反序列化測試:

    @Test
    public void whenDeserializingUsingJsonUnwrapped_thenCorrect()
            throws JsonProcessingException {
        String json = "{\"id\":1,\"firstName\":\"John\",\"lastName\":\"Doe\"}";
        String json1 = "{\"id\":1,\"name\":{\"firstName\":\"John\",\"lastName\":\"Doe\"}}";

        UnwrappedUser bean = new ObjectMapper()
                .readerFor(UnwrappedUser.class)
                .readValue(json1);
        assertEquals("John",bean.name.firstName);
    }
// 經測試,json1形式的反序列化後,name屬性是沒有值的,所以使用@JsonUnwrapped註解後,反序列化時需要注意

6.4 @JsonView

@JsonView表示包含用於序列化/反序列化的屬性的視圖。也就是我們可以通過@JsonView的方式指定需要序列化那些屬性。

// 定義一個視圖類
public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}
public class Item {
    @JsonView(Views.Public.class)
    public int id;

    @JsonView(Views.Public.class)
    public String itemName;

    @JsonView(Views.Internal.class)
    public String ownerName;
}

測試如下:

    @Test
    public void whenSerializingUsingJsonView_thenCorrect()
            throws JsonProcessingException {
        Item item = new Item(2, "book", "John");

        String result = new ObjectMapper()
                .writerWithView(Views.Public.class)
                .writeValueAsString(item);

        System.out.println(result);

        String result2 = new ObjectMapper()
                .writerWithView(Views.Internal.class)
                .writeValueAsString(item);
        System.out.println(result2);
    }
/*
{"id":2,"itemName":"book"}
{"id":2,"itemName":"book","ownerName":"John"}
*/

6.5 @JsonManagedReference, @JsonBackReference

@JsonManagedReference和@JsonBackReference可以解決嵌套關係和循環問題

首先先看這麼兩個類

public class ItemWithRef {
    public int id;
    public String itemName;
    public UserWithRef owner;
}

public class UserWithRef {
    public int id;
    public String name;
    public List<ItemWithRef> userItems;
}

這兩個類中的屬性都有各自的屬性。假設我們不做約束,看看序列化會有什麼結果

    @Test
    public void whenSerializingUsingJacksonReferenceAnnotation_thenCorrect()
            throws JsonProcessingException {
        UserWithRef user = new UserWithRef(1, "John");
        ItemWithRef item = new ItemWithRef(2, "book", user);
        user.addItem(item);

        String result = new ObjectMapper().writeValueAsString(item);

        System.out.println(result);
    }
// 此時會報錯會報一個很長很長的錯誤。這裏就不貼出來了。

我們爲兩個類加上上面兩個註解再試一次,看看會怎麼樣

public class ItemWithRef {
    public int id;
    public String itemName;

    @JsonManagedReference
    public UserWithRef owner;
}

public class UserWithRef {
    public int id;
    public String name;

    @JsonBackReference
    public List<ItemWithRef> userItems;
}

這次就可以正常序列化了{"id":2,"itemName":"book","owner":{"id":1,"name":"John"}}

**注意:**直接序列化那個對象的屬性上標註@JsonManagedReference

6.6 @JsonIdentityInfo

@JsonIdentityInfo表明在序列化/反序列化時應該使用對象標識——例如,處理無限遞歸類型的問題。

看下面類似6.5的例子

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class,
  property = "id")
public class ItemWithIdentity {
    public int id;
    public String itemName;
    public UserWithIdentity owner;
}
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class,
  property = "id")
public class UserWithIdentity {
    public int id;
    public String name;
    public List<ItemWithIdentity> userItems;
}

測試如下:

    @Test
    public void whenSerializingUsingJsonIdentityInfo_thenCorrect()
            throws JsonProcessingException {
        UserWithIdentity user = new UserWithIdentity(1, "John");
        ItemWithIdentity item = new ItemWithIdentity(2, "book", user);
        user.addItem(item);

        String result = new ObjectMapper().writeValueAsString(item);

        System.out.println(result);
    }
// {"id":2,"itemName":"book","owner":{"id":1,"name":"John","userItems":[2]}}
/*
{
    "id": 2,
    "itemName": "book",
    "owner": {
        "id": 1,
        "name": "John",
        "userItems": [
            2
        ]
    }
}
*/

注意:這裏的結果和6.5中的不一樣哦

  • 6.5中owner屬性中少了userItems屬性
  • 這裏owner屬性中的userItems中使用id來標識。

6.7 @JsonFilter

@JsonFilter註解指定在序列化期間使用的過濾器。

看一個例子:

@JsonFilter("myFilter")
public class BeanWithFilter {
    public int id;
    public String name;
}

序列化時:

    @Test
    public void whenSerializingUsingJsonFilter_thenCorrect()
            throws JsonProcessingException {
        BeanWithFilter bean = new BeanWithFilter(1, "My bean");

        // 這裏添加了一個名爲`myFilter`的過濾器,作用是:除了`name`屬性,其他的都排除在外
        FilterProvider filters
                = new SimpleFilterProvider().addFilter(
                "myFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept("name"));

        String result = new ObjectMapper()
                .writer(filters)
                .writeValueAsString(bean);

        System.out.println(result);
    }
// {"name":"My bean"}

7 自定義Jackson註解

接下來,讓我們看看如何創建自定義Jackson註解。這裏我們需要使用@JacksonAnnotationsInside註解:

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {}
// 說是自定義,其實就是使用Jackson原有的註解,將其進行組合,這個註解的作用:忽略空值屬性,並按照"name", "id", "dateCreated"排序。

使用

@CustomAnnotation
public class BeanWithCustomAnnotation {
    public int id;
    public String name;
    public Date dateCreated;
}

測試下:

@Test
public void whenSerializingUsingCustomAnnotation_thenCorrect()
  throws JsonProcessingException {
    BeanWithCustomAnnotation bean 
      = new BeanWithCustomAnnotation(1, "My bean", null);
 
    String result = new ObjectMapper().writeValueAsString(bean);

    System.out.println(result);
}
/*
{
    "name":"My bean",
    "id":1
}
*/

8 Jackson MixIn 註解

看下面的例子

public class Item2 {
    public int id;
    public String itemName;
    public User owner;
}
@JsonIgnoreType
public class MyMixInForIgnoreType {}

序列化時:

    @Test
    public void whenSerializingUsingMixInAnnotation_thenCorrect()
            throws JsonProcessingException {
        User u = new User(2,"John");

        Item2 item = new Item2(1, "book", u);

        String result = new ObjectMapper().writeValueAsString(item);
        System.out.println(result);

        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(User.class, MyMixInForIgnoreType.class); // 將User列爲忽略的類型

        String result2 = mapper.writeValueAsString(item);
        System.out.println(result2);
    }
/*
{"id":1,"itemName":"book","owner":{"id":2,"name":"John"}}
{"id":1,"itemName":"book"}
*/

9. 禁用Jackson註解

    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.USE_ANNOTATIONS);
// 這樣就禁用了註解

看一個例子

@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
    public int id;
    public String name;
}

MyBean bean = new MyBean(1, null);

如果不禁用註解序列化爲:

{"id":1}

禁用註解後的結果爲:

{
    "id":1,
    "name":null
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章