詳解jackson註解(三)jackson包含屬性、忽略屬性的註解

詳解jackson註解(三)jackson包含屬性、忽略屬性的註解

jackson中,指定包含哪些屬性、忽略哪些屬性的註解:

註解類 描述
1 JsonIgnoreProperties 用於標記忽略一個或多個屬性。可以註解在類上、構造函數、方法、字段上。
2 JsonIgnore @JsonIgnore註解用於在字段級別標記要忽略的屬性。注意:系列化和反系列化時都會被忽略。
3 JsonInclude 使用@JsonInclude可以只包含非空的屬性,也即排除值爲empty、null的屬性。
4 JsonAutoDetect 默認情況下,jackson獲取public權限的字段進行系列化和反系列化。如果沒有public修飾的字段,就會去獲取public修飾的getter/setter。使用 JsonAutoDetect註解,我們就可以修改默認的行爲。

一、JsonIgnoreProperties

用於標記忽略一個或多個屬性。可以註解在類上、構造函數、方法、字段上。

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * @author chushiyan
 * @email  [email protected]
 * @description 自關聯的權限表。一個權限有一個父權限、多個子權限
 */
@Data
public class Permission implements Serializable {

    private String id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "permission_parent_id", referencedColumnName = "permission_id")
    private Permission parent;

    // 必須使用JsonIgnoreProperties忽略parent屬性
    // 否則查詢到子權限,子權限有parent屬性,又去查父權限,會導致系列化時出現死循環
    @JsonIgnoreProperties(value = "parent")
    @OneToMany(mappedBy = "parent")
    private Set<Permission> children = new HashSet<Permission>();
   
}

二、JsonIgnore

@JsonIgnore註解用於在字段級別標記要忽略的屬性。注意:系列化和反系列化時都會被忽略。

1、bean

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.io.Serializable;

/**
 * @author chushiyan
 * @email  [email protected]
 * @description
 */
@Data
public class Article implements Serializable {

    private String id;

    private String name;

    @JsonIgnore
    private String category;
}

2、測試

 	@Test
    public void testJsonIgnore() throws JsonProcessingException {
        String json = "{"
                + "\"id\" : \"100\","
                + "\"name\" : \"詳解jackson註解","
                + "\"category\" : \"jackson\""
                + "}";
        ObjectMapper mapper = new ObjectMapper();
        Article article = mapper.readValue(json,Article.class);
        System.out.println(article);

        Article article2 = new Article();
        article2.setId("100");
        article2.setName("詳解jackson註解");
        article2.setCategory("jackson");
        String json2 = mapper.writeValueAsString(article2);
        System.out.println(json2);
}

3、控制檯輸出

Article(id=100, name=詳解jackson註解, category=null)
{"id":"100","name":"詳解jackson註解"}

反系列化時,json數據中明明包含了category值,但是最後Article對象的category屬性值依然爲null。就是因爲使用了JsonIgnore。

三、JsonInclude

我們可以使用@JsonInclude排除某些empty、null、默認值的屬性。

import com.fasterxml.jackson.annotation.JsonInclude;

/**
 * @author chushiyan
 * @email [email protected]
 * @description
 */
// 使用JsonInclude註解指明只包含非null的屬性,即排除值爲null的屬性
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result {

    private boolean flag;// 是否成功

    private Integer code;// 返回碼

    private String message;// 返回信息

    private Object data;// 返回數據

    public Result() {
    }

    public Result(boolean flag, Integer code, String message) {
        this.flag = flag;
        this.code = code;
        this.message = message;
    }

    public Result(boolean flag, Integer code, String message, Object data) {
        this.flag = flag;
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    
    @Override
    public String toString() {
        return "Result{" +
                "flag=" + flag +
                ", code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }

}

2、controller

 	@GetMapping("/test8")
    public Result testJsonInclude(){
        return new  Result(true,200,"查詢成功");
    }

沒有在Result類上加 @JsonInclude(JsonInclude.Include.NON_NULL) 註解時,返回的響應:

{
    "flag": true,
    "code": 200,
    "message": "查詢成功",
    "data": null
}

加了之後的返回的響應:

{
    "flag": true,
    "code": 200,
    "message": "查詢成功"
}

四、 JsonAutoDetect

默認情況下,jackson獲取public權限的字段進行系列化和反系列化。如果沒有public權限的字段,就會去獲取public修飾的getter/setter。使用 JsonAutoDetect註解,我們就可以修改默認的行爲。比如,下面的案例,即使字段都是private的、也沒有getter/setter,也照樣獲取字段。

1、bean

首先,我們定義一個屬性id/name都私有的而且沒有getter/setter的一個bean

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import java.io.Serializable;

/**
 * @author chushiyan
 * @email [email protected]
 * @description
 */
//@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean implements Serializable {

    private String id;

    private String name;

    public PrivateBean() {
    }

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

    @Override
    public String toString() {
        return "PrivateBean{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

2、反系列化測試:

 	@Test
    public void testJsonAutoDetect() throws JsonProcessingException {
        String json = "{"
                + "\"id\" : \"10\","
                + "\"name\" : \"chushiyan\""
                + "}";
        ObjectMapper mapper = new ObjectMapper();
        PrivateBean bean = mapper.readValue(json, PrivateBean.class);
        System.out.println(bean);
    }

報錯:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id" (class com.chushiyan.test.entity.PrivateBean), not marked as ignorable (0 known properties: ])
 at [Source: (String)"{"id" : "10","name" : "chushiyan"}"; line: 1, column: 10] (through reference chain: com.chushiyan.test.entity.PrivateBean["id"])

3、系列化測試

 	@Test
    public void testJsonAutoDetect2() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        PrivateBean bean = new PrivateBean("11", "chushiyan");
        String json = mapper.writeValueAsString(bean);
        System.out.println(json);
    }

報錯:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.chushiyan.test.entity.PrivateBean and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

4、bean上加上註解

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import java.io.Serializable;

/**
 * @author chushiyan
 * @email [email protected]
 * @description
 */
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean implements Serializable {

    private String id;

    private String name;

    public PrivateBean() {
    }

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

    @Override
    public String toString() {
        return "PrivateBean{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

5、再次分別測試反系列化、系列化

都運行正常,分別打印:

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