美文网首页
详解jackson注解(三)jackson包含属性、忽略属性的注

详解jackson注解(三)jackson包含属性、忽略属性的注

作者: chushiyan | 来源:发表于2019-12-07 20:39 被阅读0次

    详解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  chushiyan0415@163.com
     * @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  chushiyan0415@163.com
     * @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 chushiyan0415@163.com
     * @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 chushiyan0415@163.com
     * @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 chushiyan0415@163.com
     * @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"}
    

    相关文章

      网友评论

          本文标题:详解jackson注解(三)jackson包含属性、忽略属性的注

          本文链接:https://www.haomeiwen.com/subject/aoxpgctx.html