亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

Jackson注解詳解

 

1. 概述

在本文中,我們將深入研究Jackson注解。

我們將看到如何使用現(xiàn)有的注釋,如何創(chuàng)建自定義的注釋,最后—如何禁用它們。

2. Jackson序列化注解

首先,我們將查看序列化注釋。

2.1. @JsonAnyGetter

@JsonAnyGetter注釋允許靈活地使用映射字段作為標(biāo)準(zhǔn)屬性。

下面是一個(gè)快速的例子——ExtendableBean實(shí)體擁有name屬性和一組可擴(kuò)展屬性,它們以鍵/值對(duì)的形式存在:

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

當(dāng)我們序列化這個(gè)實(shí)體的一個(gè)實(shí)例時(shí),我們會(huì)得到Map中所有的鍵值作為標(biāo)準(zhǔn)的普通屬性:

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

這里是如何序列化這個(gè)實(shí)體看起來(lái)像在實(shí)踐:

@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
  throws JsonProcessingException {
 
    ExtendableBean bean = new ExtendableBean("My bean");
    bean.add("attr1", "val1");
    bean.add("attr2", "val2");
 
    String result = new ObjectMApper().writeValueAsString(bean);
 
    assertThat(result, containsString("attr1"));
    assertThat(result, containsString("val1"));
}

我們還可以使用可選參數(shù)enabled為false來(lái)禁用@JsonAnyGetter()。在本例中,映射將被轉(zhuǎn)換為JSON,并在序列化之后出現(xiàn)在properties變量下。

2.2. @JsonGetter

@JsonGetter注釋是@JsonProperty注釋的替代品,它將方法標(biāo)記為getter方法。

在下面的例子中-我們指定getTheName()方法作為MyBean實(shí)體的name屬性的getter方法:

public class MyBean {
    public int id;
    private String name;
 
    @JsonGetter("name")
    public String getTheName() {
        return name;
    }
}

這是如何在實(shí)踐中運(yùn)作的:

@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
  throws JsonProcessingException {
 
    MyBean bean = new MyBean(1, "My bean");
 
    String result = new ObjectMapper().writeValueAsString(bean);
 
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
}

2.3. @JsonPropertyOrder

我們可以使用@JsonPropertyOrder注釋來(lái)指定序列化時(shí)屬性的順序。

讓我們?yōu)镸yBean實(shí)體的屬性設(shè)置一個(gè)自定義順序:

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

這是序列化的輸出:

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

還有一個(gè)簡(jiǎn)單的測(cè)試:

@Test
public void whenSerializingUsingJsonPropertyOrder_thenCorrect()
  throws JsonProcessingException {
 
    MyBean bean = new MyBean(1, "My bean");
 
    String result = new ObjectMapper().writeValueAsString(bean);
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
}

我們還可以使用@JsonPropertyOrder(alphabetic=true)按字母順序排列屬性。在這種情況下,序列化的輸出將是:

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

2.4. @JsonRawValue

@JsonRawValue注釋可以指示Jackson按原樣序列化屬性。

在下面的例子中,我們使用@JsonRawValue嵌入一些定制的JSON作為一個(gè)實(shí)體的值:

public class RawBean {
    public String name;
 
    @JsonRawValue
    public String json;
}

序列化實(shí)體的輸出為:

{
    "name":"My bean",
    "json":{
        "attr":false
    }
}

還有一個(gè)簡(jiǎn)單的測(cè)試:

@Test
public void whenSerializingUsingJsonRawValue_thenCorrect()
  throws JsonProcessingException {
 
    RawBean bean = new RawBean("My bean", "{"attr":false}");
 
    String result = new ObjectMapper().writeValueAsString(bean);
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("{"attr":false}"));
}

我們還可以使用可選的布爾參數(shù)值來(lái)定義這個(gè)注釋是否是活動(dòng)的。

2.5. @JsonValue

@JsonValue表示庫(kù)將使用一個(gè)方法來(lái)序列化整個(gè)實(shí)例。

例如,在枚舉中,我們用@JsonValue注釋getName,這樣任何這樣的實(shí)體都可以通過(guò)其名稱序列化:

public enum TypeEnumWithValue {
    TYPE1(1, "Type A"), TYPE2(2, "Type 2");
 
    private Integer id;
    private String name;
 
    // standard constructors
 
    @JsonValue
    public String getName() {
        return name;
    }
}

我們的測(cè)試:

@Test
public void whenSerializingUsingJsonValue_thenCorrect()
  throws JsonParseException, IOException {
 
    String enumAsString = new ObjectMapper()
      .writeValueAsString(TypeEnumWithValue.TYPE1);
 
    assertThat(enumAsString, is(""Type A""));
}

2.6. @JsonRootName

如果啟用了包裝,則使用@JsonRootName注釋來(lái)指定要使用的根包裝器的名稱。

包裝意味著不將用戶序列化為以下內(nèi)容:

它會(huì)像這樣包裝:

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

那么,讓我們來(lái)看一個(gè)例子——我們將使用@JsonRootName注釋來(lái)表示這個(gè)潛在的包裝實(shí)體的名稱:

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

默認(rèn)情況下,包裝器的名稱將是類的名稱- UserWithRoot。通過(guò)使用注釋,我們得到了看起來(lái)更干凈的用戶:

@Test
public void whenSerializingUsingJsonRootName_thenCorrect()
  throws JsonProcessingException {
 
    UserWithRoot user = new User(1, "John");
 
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
    String result = mapper.writeValueAsString(user);
 
    assertThat(result, containsString("John"));
    assertThat(result, containsString("user"));
}

這是序列化的輸出:

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

自Jackson 2.4以來(lái),一個(gè)新的可選參數(shù)名稱空間可用于XML等數(shù)據(jù)格式。如果我們添加它,它將成為完全限定名的一部分:

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

如果我們用XmlMapper序列化它,輸出將是:

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

2.7. @JsonSerialize

讓我們看一個(gè)簡(jiǎn)單的例子。我們將使用@JsonSerialize用CustomDateSerializer來(lái)序列化eventDate屬性:

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

下面是簡(jiǎn)單的自定義Jackson序列化器:

public class CustomDateSerializer extends StdSerializer<Date> {
 
    private static SimpleDateFormat formatter 
      = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
 
    public CustomDateSerializer() { 
        this(null); 
    } 
 
    public CustomDateSerializer(Class<Date> t) {
        super(t); 
    }
 
    @Override
    public void serialize(
      Date value, JsonGenerator gen, SerializerProvider arg2) 
      throws IOException, JsonProcessingException {
        gen.writeString(formatter.format(value));
    }
}

讓我們?cè)跍y(cè)試中使用這些:

@Test
public void whenSerializingUsingJsonSerialize_thenCorrect()
  throws JsonProcessingException, ParseException {
 
    SimpleDateFormat df
      = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
 
    String toParse = "20-12-2014 02:30:00";
    Date date = df.parse(toParse);
    EventWithSerializer event = new EventWithSerializer("party", date);
 
    String result = new ObjectMapper().writeValueAsString(event);
    assertThat(result, containsString(toParse));
}

Jackson反序列化注解

接下來(lái)——讓我們研究Jackson反序列化注解。

3.1. @JsonCreator

我們可以使用@JsonCreator注釋來(lái)調(diào)優(yōu)反序列化中使用的構(gòu)造器/工廠。

當(dāng)我們需要反序列化一些與我們需要獲取的目標(biāo)實(shí)體不完全匹配的JSON時(shí),它非常有用。

我們來(lái)看一個(gè)例子;說(shuō)我們需要反序列化以下JSON:

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

但是,在我們的目標(biāo)實(shí)體中沒(méi)有theName字段—只有name字段。現(xiàn)在,我們不想改變實(shí)體本身—我們只需要對(duì)數(shù)據(jù)編出過(guò)程進(jìn)行更多的控制—通過(guò)使用@JsonCreator和@JsonProperty注釋來(lái)注釋構(gòu)造函數(shù):

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;
    }
}

讓我們來(lái)看看這是怎么回事:

@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
  throws IOException {
 
    String json = "{"id":1,"theName":"My bean"}";
 
    BeanWithCreator bean = new ObjectMapper()
      .readerFor(BeanWithCreator.class)
      .readValue(json);
    assertEquals("My bean", bean.name);
}

3.2. @JacksonInject

@JacksonInject表示屬性將從注入中獲得其值,而不是從JSON數(shù)據(jù)中。

在下面的例子中,我們使用@JacksonInject注入屬性id:

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

它是這樣工作的:

@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
  throws IOException {
 
    String json = "{"name":"My bean"}";
    
    InjectableValues inject = new InjectableValues.Std()
      .addValue(int.class, 1);
    BeanWithInject bean = new ObjectMapper().reader(inject)
      .forType(BeanWithInject.class)
      .readValue(json);
    
    assertEquals("My bean", bean.name);
    assertEquals(1, bean.id);
}

3.3. @JsonAnySetter

@JsonAnySetter允許我們靈活地使用映射作為標(biāo)準(zhǔn)屬性。在反序列化時(shí),JSON的屬性將被添加到映射中。

讓我們看看這是如何工作的-我們將使用@JsonAnySetter來(lái)反序列化實(shí)體ExtendableBean:

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"
}

而這一切是如何聯(lián)系在一起的:

@Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
  throws IOException {
    String json
      = "{"name":"My bean","attr2":"val2","attr1":"val1"}";
 
    ExtendableBean bean = new ObjectMapper()
      .readerFor(ExtendableBean.class)
      .readValue(json);
    
    assertEquals("My bean", bean.name);
    assertEquals("val2", bean.getProperties().get("attr2"));
}

3.4. @JsonSetter

@JsonSetter是@JsonProperty的替代方法—它將方法標(biāo)記為setter方法。

當(dāng)我們需要讀取一些JSON數(shù)據(jù),但目標(biāo)實(shí)體類與該數(shù)據(jù)不完全匹配時(shí),這非常有用,因此我們需要調(diào)優(yōu)流程以使其適合該數(shù)據(jù)。

在下面的例子中,我們將指定方法setTheName()作為MyBean實(shí)體中name屬性的setter:

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

現(xiàn)在,當(dāng)我們需要unmarshall一些JSON數(shù)據(jù)-這是完美的工作:

@Test
public void whenDeserializingUsingJsonSetter_thenCorrect()
  throws IOException {
 
    String json = "{"id":1,"name":"My bean"}";
 
    MyBean bean = new ObjectMapper()
      .readerFor(MyBean.class)
      .readValue(json);
    assertEquals("My bean", bean.getTheName());
}

3.5. @JsonDeserialize

@JsonDeserialize表示使用自定義反序列化器。

讓我們看看這是如何實(shí)現(xiàn)的-我們將使用@JsonDeserialize來(lái)反序列化eventDate屬性與CustomDateDeserializer:

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

這是自定義反序列化器:

public class CustomDateDeserializer
  extends StdDeserializer<Date> {
 
    private static SimpleDateFormat formatter
      = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
 
    public CustomDateDeserializer() { 
        this(null); 
    } 
 
    public CustomDateDeserializer(Class<?> vc) { 
        super(vc); 
    }
 
    @Override
    public Date deserialize(
      JsonParser jsonparser, DeserializationContext context) 
      throws IOException {
        
        String date = jsonparser.getText();
        try {
            return formatter.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

這是背靠背的測(cè)試:

@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
  throws IOException {
 
    String json
      = "{"name":"party","eventDate":"20-12-2014 02:30:00"}";
 
    SimpleDateFormat df
      = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
    EventWithSerializer event = new ObjectMapper()
      .readerFor(EventWithSerializer.class)
      .readValue(json);
    
    assertEquals(
      "20-12-2014 02:30:00", df.format(event.eventDate));
}

3.6 @JsonAlias

@JsonAlias在反序列化期間為屬性定義一個(gè)或多個(gè)替代名稱。

讓我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看看這個(gè)注釋是如何工作的:

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

在這里,我們有一個(gè)POJO,我們想用fName、f_name和firstName等值反序列化JSON到POJO的firstName變量中。

這里有一個(gè)測(cè)試,確保這個(gè)注釋像expecte一樣工作:

@Test
public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
    String json = "{"fName": "John", "lastName": "Green"}";
    AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
    assertEquals("John", aliasBean.getFirstName());
}

4. Jackson屬性包含注釋

4.1. @JsonIgnoreProperties

@JsonIgnoreProperties是一個(gè)類級(jí)注釋,它標(biāo)記Jackson將忽略的一個(gè)屬性或一列屬性。

讓我們來(lái)看一個(gè)忽略屬性id的例子:

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

下面是確保忽略發(fā)生的測(cè)試:

@Test
public void whenSerializingUsingJsonIgnoreProperties_thenCorrect()
  throws JsonProcessingException {
 
    BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
 
    String result = new ObjectMapper()
      .writeValueAsString(bean);
    
    assertThat(result, containsString("My bean"));
    assertThat(result, not(containsString("id")));
}

為了毫無(wú)例外地忽略JSON輸入中的任何未知屬性,我們可以對(duì)@JsonIgnoreProperties注釋設(shè)置ignoreUnknown=true。

4.2. @JsonIgnore

@JsonIgnore注釋用于在字段級(jí)別標(biāo)記要忽略的屬性。

讓我們使用@JsonIgnore來(lái)忽略序列化中的屬性id:

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

確保id被成功忽略的測(cè)試:

@Test
public void whenSerializingUsingJsonIgnore_thenCorrect()
  throws JsonProcessingException {
 
    BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
 
    String result = new ObjectMapper()
      .writeValueAsString(bean);
    
    assertThat(result, containsString("My bean"));
    assertThat(result, not(containsString("id")));
}

4.3. @JsonIgnoreType

@JsonIgnoreType將注釋類型的所有屬性標(biāo)記為忽略。

讓我們使用注釋來(lái)標(biāo)記所有類型名稱的屬性被忽略:

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

這里有一個(gè)簡(jiǎn)單的測(cè)試,確保忽略工作正確:

@Test
public void whenSerializingUsingJsonIgnoreType_thenCorrect()
  throws JsonProcessingException, ParseException {
 
    User.Name name = new User.Name("John", "Doe");
    User user = new User(1, name);
 
    String result = new ObjectMapper()
      .writeValueAsString(user);
 
    assertThat(result, containsString("1"));
    assertThat(result, not(containsString("name")));
    assertThat(result, not(containsString("John")));
}

4.4. @JsonInclude

我們可以使用@JsonInclude來(lái)排除具有空/空/默認(rèn)值的屬性。

讓我們看一個(gè)例子-排除null從序列化:

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

下面是完整的測(cè)試:

public void whenSerializingUsingJsonInclude_thenCorrect()
  throws JsonProcessingException {
 
    MyBean bean = new MyBean(1, null);
 
    String result = new ObjectMapper()
      .writeValueAsString(bean);
    
    assertThat(result, containsString("1"));
    assertThat(result, not(containsString("name")));
}

4.5. @JsonAutoDetect

@JsonAutoDetect可以覆蓋哪些屬性可見(jiàn),哪些不可見(jiàn)的默認(rèn)語(yǔ)義。

讓我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看看這個(gè)注釋是如何非常有用的——讓我們啟用序列化私有屬性:

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

測(cè)試:

@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
  throws JsonProcessingException {
 
    PrivateBean bean = new PrivateBean(1, "My bean");
 
    String result = new ObjectMapper()
      .writeValueAsString(bean);
    
    assertThat(result, containsString("1"));
    assertThat(result, containsString("My bean"));
}

5. Jackson多態(tài)類型處理注釋

接下來(lái),讓我們看看Jackson多態(tài)類型處理注釋:

  • @JsonTypeInfo——指示要在序列化中包含什么類型信息的詳細(xì)信息
  • @JsonSubTypes——指示注釋類型的子類型
  • @JsonTypeName—定義了一個(gè)用于注釋類的邏輯類型名

讓我們看一個(gè)更復(fù)雜的例子,使用所有這三個(gè)——@JsonTypeInfo, @JsonSubTypes,和@JsonTypeName——來(lái)序列化/反序列化實(shí)體Zoo:

public class Zoo {
    public Animal animal;
 
    @JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME, 
      include = 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;
    }
 
    @JsonTypeName("dog")
    public static class Dog extends Animal {
        public double barkVolume;
    }
 
    @JsonTypeName("cat")
    public static class Cat extends Animal {
        boolean likesCream;
        public int lives;
    }
}

當(dāng)我們進(jìn)行序列化時(shí):

@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);
 
    assertThat(result, containsString("type"));
    assertThat(result, containsString("dog"));
}

下面是將動(dòng)物園實(shí)例與狗序列化將得到的結(jié)果:

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

現(xiàn)在反序列化-讓我們從以下JSON輸入開(kāi)始:

{
    "animal":{
        "name":"lacy",
        "type":"cat"
    }
}

讓我們看看它是如何被分解到一個(gè)動(dòng)物園實(shí)例的:

@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
    String json = "{"animal":{"name":"lacy","type":"cat"}}";
 
    Zoo zoo = new ObjectMapper()
      .readerFor(Zoo.class)
      .readValue(json);
 
    assertEquals("lacy", zoo.animal.name);
    assertEquals(Zoo.Cat.class, zoo.animal.getClass());
}

6. Jackson通用注解

接下來(lái)——讓我們討論Jackson的一些更通用的注釋。

6.1. @JsonProperty

我們可以添加@JsonProperty注釋來(lái)表示JSON中的屬性名。

當(dāng)我們處理非標(biāo)準(zhǔn)的getter和setter時(shí),讓我們使用@JsonProperty來(lái)序列化/反序列化屬性名:

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;
    }
}

我們的測(cè)試:

@Test
public void whenUsingJsonProperty_thenCorrect()
  throws IOException {
    MyBean bean = new MyBean(1, "My bean");
 
    String result = new ObjectMapper().writeValueAsString(bean);
    
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
 
    MyBean resultBean = new ObjectMapper()
      .readerFor(MyBean.class)
      .readValue(result);
    assertEquals("My bean", resultBean.getTheName());
}

6.2. @JsonFormat

@JsonFormat注釋在序列化日期/時(shí)間值時(shí)指定一種格式。

在下面的例子中,我們使用@JsonFormat來(lái)控制屬性eventDate的格式:

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

下面是測(cè)試:

@Test
public void whenSerializingUsingJsonFormat_thenCorrect()
  throws JsonProcessingException, ParseException {
    SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
 
    String toParse = "20-12-2014 02:30:00";
    Date date = df.parse(toParse);
    EventWithFormat event = new EventWithFormat("party", date);
    
    String result = new ObjectMapper().writeValueAsString(event);
    
    assertThat(result, containsString(toParse));
}

6.3. @JsonUnwrapped

@JsonUnwrapped定義了在序列化/反序列化時(shí)應(yīng)該被解包裝/扁平化的值。

我們來(lái)看看它是如何工作的;我們將使用注釋來(lái)展開(kāi)屬性名:

public class UnwrappedUser {
    public int id;
 
    @JsonUnwrapped
    public Name name;
 
    public static class Name {
        public String firstName;
        public String lastName;
    }
}

現(xiàn)在讓我們序列化這個(gè)類的一個(gè)實(shí)例:

@Test
public void whenSerializingUsingJsonUnwrapped_thenCorrect()
  throws JsonProcessingException, ParseException {
    UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
    UnwrappedUser user = new UnwrappedUser(1, name);
 
    String result = new ObjectMapper().writeValueAsString(user);
    
    assertThat(result, containsString("John"));
    assertThat(result, not(containsString("name")));
}

下面是輸出的樣子-靜態(tài)嵌套類的字段與其他字段一起展開(kāi):

{
    "id":1,
    "firstName":"John",
    "lastName":"Doe"
}

6.4. @JsonView

@JsonView表示將包含該屬性進(jìn)行序列化/反序列化的視圖。

我們將使用@JsonView來(lái)序列化項(xiàng)目實(shí)體的實(shí)例。

讓我們從視圖開(kāi)始:

public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

現(xiàn)在這是Item實(shí)體,使用視圖:

public class Item {
    @JsonView(Views.Public.class)
    public int id;
 
    @JsonView(Views.Public.class)
    public String itemName;
 
    @JsonView(Views.Internal.class)
    public String ownerName;
}

最后-完整測(cè)試:

@Test
public void whenSerializingUsingJsonView_thenCorrect()
  throws JsonProcessingException {
    Item item = new Item(2, "book", "John");
 
    String result = new ObjectMapper()
      .writerWithView(Views.Public.class)
      .writeValueAsString(item);
 
    assertThat(result, containsString("book"));
    assertThat(result, containsString("2"));
    assertThat(result, not(containsString("John")));
}

6.5. @JsonManagedReference, @JsonBackReference

@JsonManagedReference和@JsonBackReference注釋可以處理父/子關(guān)系并在循環(huán)中工作。

在下面的例子中-我們使用@JsonManagedReference和@JsonBackReference來(lái)序列化我們的ItemWithRef實(shí)體:

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

我們的UserWithRef實(shí)體:

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

測(cè)試:

@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);
 
    assertThat(result, containsString("book"));
    assertThat(result, containsString("John"));
    assertThat(result, not(containsString("userItems")));
}

6.6. @JsonIdentityInfo

@JsonIdentityInfo表示在序列化/反序列化值時(shí)應(yīng)該使用對(duì)象標(biāo)識(shí)—例如,用于處理無(wú)限遞歸類型的問(wèn)題。

在下面的例子中-我們有一個(gè)ItemWithIdentity實(shí)體,它與UserWithIdentity實(shí)體具有雙向關(guān)系:

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

和UserWithIdentity實(shí)體:

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

現(xiàn)在,讓我們看看無(wú)限遞歸問(wèn)題是如何處理的:

@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);
 
    assertThat(result, containsString("book"));
    assertThat(result, containsString("John"));
    assertThat(result, containsString("userItems"));
}

下面是序列化的項(xiàng)目和用戶的完整輸出:

{
    "id": 2,
    "itemName": "book",
    "owner": {
        "id": 1,
        "name": "John",
        "userItems": [
            2
        ]
    }
}

6.7. @JsonFilter

@JsonFilter注釋指定要在序列化期間使用的過(guò)濾器。

讓我們看一個(gè)例子;首先,我們定義實(shí)體,并指向過(guò)濾器:

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

現(xiàn)在,在完整的測(cè)試中,我們定義了過(guò)濾器——它排除了序列化中除了name之外的所有其他屬性:

@Test
public void whenSerializingUsingJsonFilter_thenCorrect()
  throws JsonProcessingException {
    BeanWithFilter bean = new BeanWithFilter(1, "My bean");
 
    FilterProvider filters 
      = new SimpleFilterProvider().addFilter(
        "myFilter", 
        SimpleBeanPropertyFilter.filterOutAllExcept("name"));
 
    String result = new ObjectMapper()
      .writer(filters)
      .writeValueAsString(bean);
 
    assertThat(result, containsString("My bean"));
    assertThat(result, not(containsString("id")));
}

7. Jackson自定義注釋

接下來(lái),讓我們看看如何創(chuàng)建自定義Jackson注釋。我們可以使用@JacksonAnnotationsInside注釋:

@Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotationsInside
    @JsonInclude(Include.NON_NULL)
    @JsonPropertyOrder({ "name", "id", "dateCreated" })
    public @interface CustomAnnotation {}

現(xiàn)在,如果我們對(duì)一個(gè)實(shí)體使用新的注釋:

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

我們可以看到它是如何將現(xiàn)有的注解組合成一個(gè)更簡(jiǎn)單的、自定義的注解,我們可以使用它作為速記:

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

序列化過(guò)程的輸出:

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

8. Jackson MixIn 注解

接下來(lái)——讓我們看看如何使用Jackson MixIn注釋。

讓我們使用MixIn注釋——例如——忽略類型User的屬性:

public class Item {
    public int id;
    public String itemName;
    public User owner;
}

@JsonIgnoreType
public class MyMixInForIgnoreType {}

讓我們來(lái)看看這是怎么回事:

@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect() 
  throws JsonProcessingException {
    Item item = new Item(1, "book", null);
 
    String result = new ObjectMapper().writeValueAsString(item);
    assertThat(result, containsString("owner"));
 
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
 
    result = mapper.writeValueAsString(item);
    assertThat(result, not(containsString("owner")));
}

9. 禁用Jackson注解

最后,讓我們看看如何禁用所有Jackson注釋。我們可以通過(guò)禁用MapperFeature來(lái)做到這一點(diǎn)。如下例所示:

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

現(xiàn)在,禁用注釋后,這些應(yīng)該沒(méi)有效果,庫(kù)的默認(rèn)值應(yīng)該適用:

@Test
public void whenDisablingAllAnnotations_thenAllDisabled()
  throws IOException {
    MyBean bean = new MyBean(1, null);
 
    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.USE_ANNOTATIONS);
    String result = mapper.writeValueAsString(bean);
    
    assertThat(result, containsString("1"));
    assertThat(result, containsString("name"));

禁用注釋之前序列化的結(jié)果:

{"id":1}

禁用注釋后序列化的結(jié)果:

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

10. 結(jié)論

本教程對(duì)Jackson注釋進(jìn)行了深入的研究,只觸及了正確使用它們所能獲得的靈活性的表面。

分享到:
標(biāo)簽:Jackson
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定