• Jackson的基本用法与拓展


    目录

      一、先搞两个测试需要使用的类

      二、简单操作:obj与json互转

        2.1、对象转json字符串

        2.2、json字符串转对象

    三、拓展需求

      3.1、对象转json时,忽略某个字段

        3.2、对象转json时,自定义json中的属性名

        3.3、对象转json时,忽略对象中为null或者""的属性

        3.4、json转对象时,忽略json中未知的属性

        3.5、对象转json时,生成格式化的json字符串

    一、先搞两个测试需要使用的类

      分别是Staff(员工)和Department(部门)

    package cn.ganlixin.demo;
    
    import lombok.Data;
    
    @Data
    public class Department {
    
        private String depName;
        private String addr;
        private String superior;
    }
    

      

    package cn.ganlixin.demo;
    
    import lombok.Data;
    
    import java.util.List;
    import java.util.Map;
    
    @Data
    public class Staff {
        private int id;
        private String name;
        private boolean isAdult;
        private List<String> languages;
        private Map<String, Object> scores;
        private Department department;
    }
    

      

    二、简单操作:obj与json互转

    2.1、对象转json字符串

      核心代码段

    ObjectMapper mapper = new ObjectMapper();
    String jsonStr = mapper.writeValueAsString(Object obj);
    // Object就是需要序列化(转换为json字符串的对象)
    

      

      示例

    /**
     * 对象  转为  json字符串
     */
    @Test
    public void test1() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
    
        List<String> languages = new ArrayList<>();
        languages.add("Java");
        languages.add("PHP");
        languages.add("Python");
        String languagesJsonStr = mapper.writeValueAsString(languages);
        System.out.println(languagesJsonStr);
        // ["Java","PHP","Python"]
    
        Map<String, Object> scores = new HashMap<>();
        scores.put("math", 59);
        scores.put("english", 58);
        String scoresJsonStr = mapper.writeValueAsString(scores);
        System.out.println(scoresJsonStr);
        // {"english":58,"math":59}
    
        Department department = new Department();
        department.setDepName("QA");
        department.setAddr("beijing");
        department.setSuperior("小强");
        String departmentJsonStr = mapper.writeValueAsString(department);
        System.out.println(departmentJsonStr);
        // {"depName":"QA","addr":"beijing","superior":"小强"}
    }
    

      

    2.2、json字符串转对象

      核心代码

    ObjectMapper mapper = new ObjectMapper();
    Staff staff = mapper.readValue(jsonStr, Staff.class); 
    // 表示将json字符串的内容转换为Staff类的对象
    

      

      示例:

    /**
     * 将json字符串转换为对象
     */
    @Test
    public void test2() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
    
        String languageJsonStr = "["Java","PHP","Python"]";
        final List languages = mapper.readValue(languageJsonStr, List.class);
        System.out.println(languages);
        // [Java, PHP, Python]
    
        String scoresJsonStr = "{"english":58,"math":59}";
        Map<String, Object> scores = mapper.readValue(scoresJsonStr, Map.class);
        System.out.println(scores);
        // {english=58, math=59}
    
        String departmentJsonStr = "{"depName":"QA","addr":"beijing","superior":"小强"}";
        final Department department = mapper.readValue(departmentJsonStr, Department.class);
        System.out.println(department);
        // Department(depName=QA, addr=beijing, superior=小强)
    }
    

      

    三、拓展需求

    3.1、对象转json时,忽略某个字段

      有些场景中,某些字段在序列化为json的时候,应该省略掉,比如一个员工的工资,某个用户的密码.....

      案例:假设有一个department对象,在转为json时,superior(上级)这个字段不能出现在转换后的json中

      方案1:在不需要参与json序列化的字段前增加@JsonIgnore注解即可

    @Data
    public class Department {
    
        private String depName;
        private String addr;
    
        @JsonIgnore   // 加了@JsonIgnor字段后,superior字段将不参与json序列化
        private String superior;
    }
    

      

       方案2:在类上面使用@JsonIgnoreProperties({"field1", "field2"})来指定哪些字段不参与json序列化

    @Data
    @JsonIgnoreProperties({"superior"}) 
    // 在@JsonIgnoreProperties注解中指定不参与json序列化的字段即可(接收字符串数组)
    public class Department {
    
        private String depName;
        private String addr;
        private String superior;
    }
    

      

      测试

    /**
     * 对象转json时,忽略某个字段
     */
    @Test
    public void test3() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
    
        Department department = new Department();
        department.setDepName("QA");
        department.setAddr("beijing");
        department.setSuperior("小强");
    
        final String departmentJsonStr = mapper.writeValueAsString(department);
        System.out.println(departmentJsonStr);
        // {"depName":"QA","addr":"beijing"}
    }
    

      

    3.2、对象与json互转时,自定义json中的属性名

      经常会碰到我们的模型类中定义的属性名称,与外部传入的json字符串中的名称不相同的情况,比如Department类中的superior属性,接收到外部系统传过来的json字符串中,对应upLevel字段。

      在序列化时(obj->json)和反序列化时(json->obj)都需要解决上面superior到upLevel的对应问题,Jackson中提供了一个@JsonProperty注解来解决这个问题

    @Data
    public class Department {
        private String depName;
        private String addr;
    
        @JsonProperty("upLevel")
        // 指定序列化与反序列化时,superior属性对应的名称:序列化时,superior对应到upLevel属性,反序列化时,upLevel对应到superior属性
        private String superior;
    }
    

      

      示例:

    /**
     * 对象与json互转时,自定义对应名称
     */
    @Test
    public void test4() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
    
        Department department1 = new Department();
        department1.setDepName("QA");
        department1.setAddr("beijing");
        department1.setSuperior("小强");
    
        // 对象序列化为json字符串,注意superior属性转json时会变为upLevel
        String departmentJsonStr = mapper.writeValueAsString(department1);
        System.out.println(departmentJsonStr);
        // {"depName":"QA","addr":"beijing","upLevel":"小强"}
    
        // 利用上面序列化的字符串,反序列为对象,upLevel字段会对应到Department对象的superior属性
        Department department2 = mapper.readValue(departmentJsonStr, Department.class);
        System.out.println(department2);
        // Department(depName=QA, addr=beijing, superior=小强) 
    }
    

      

     3.3、对象转json时,忽略对象中为null或者""的属性

      这个需求是这样的,对象中,有的属性值是null或者空字符串,此时,我们不希望转换后的json字符串中包含该属性值为null或者空字符串的字段。

      比如Department类中的superior属性,对于老板来说,没有上级,则superior的值为null或者"",此时希望序列化后的json字符串省略superior字段(这与前面的省略某个字段不同)。

      Jackson在将对象序列化为json字符串时,默认是在类级别添加了@JsonInclude(JsonInclude.Include.ALWAYS)注解,表示默认将对象的所有字段都序列化(即使属性值为null或者空字符串)。

      要实现忽略对象中属性值为null或者""的属性值,可以这样做:

      方案1:

        @JsonInclude(JsonInclude.Include.NON_NULL)  可以加在指定的字段前(局部),也可以加在类级别上(全局),当属性值不为null的时候才会参加序列化

        @JsonInclude(JsonInclude.Include.NON_EMPTY) 可以加在指定的字段前(局部),也可以加在类级别上(全局),当设置属性值为null或者""的时候,该属性不会参加序列化;

        注意,对于上面两个注解,如果类中声明该属性有默认值,即使没有为该属性设置属性值,那么该属性仍旧会参加序列化。

    @Data
    public class Department {
        private String depName;
        private String addr;
    
        @JsonInclude(JsonInclude.Include.NON_NULL) // 加在指定的字段前,当属性值不为null的时候才会参加序列化
        private String superior;
    }
    

      

      方案2:

        方案1使用于要序列化的类数量不多的情况,如果要进行序列化的类非常多,并且都需要忽略属性值为null或者""的属性,那么对每一个类进行设置@JsonInclude(xxxx)也是很麻烦的,这个时候,我们可以从ObjectMapper上进行配置,使用配置后的ObjectMapper,那么在序列化的时候,自动回忽略值为null或者""的属性值。 

    /**
     * 全局设置对象转json时忽略值为null或者""的属性
     */
    @Test
    public void test7() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        // 设置忽略null和""的属性值,这里的Include与方案1的一致
        mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    
        Department department1 = new Department();
        department1.setDepName("QA");
        department1.setAddr("");
        department1.setSuperior(null);
    
        String depJsonStr = mapper.writeValueAsString(department1);
        System.out.println(depJsonStr);
        // {"depName":"QA"}
    }

     

    3.4、json转对象时,忽略json中未知的属性

      这个场景是指,json中有一个字段,在类中找不多与之对应的属性,此时如果强请转换为指定类,那么就会报错

    @Test
    public void test8() throws IOException {
        // 注意,json串中多了age字段,而Department类中并无该属性(且无属性与之对应,比如使用@JsonProperty进行设置)
        String json = "{"depName":"QA","addr":"beijing", "age":99}";
    
        ObjectMapper mapper = new ObjectMapper();
        final Department department = mapper.readValue(json, Department.class);
        System.out.println(department);
    }
    

      上面的运行时会报错:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "age" (class cn.ganlixin.demo.Department), not marked as ignorable....

      这个情况,可以通过设置mapper来解决问题

    /**
     * 忽略json中未知的字段名
     */
    @Test
    public void test9() throws IOException {
        String json = "{"depName":"QA","addr":"beijing", "age":99}";
    
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);  // 表示遇到未知属性时,不会报错
        final Department department = mapper.readValue(json, Department.class);
        System.out.println(department);
        // Department(depName=QA, addr=beijing, superior=null)
    }
    

       

    3.5、对象转json时,生成格式化的json字符串

      在writeValueAsString(Object obj)之前,mapper先调用writerWithDefaultPrettyPrinter()方法即可

    @Test
    public void test6() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
    
        Department department1 = new Department();
        department1.setDepName("QA");
        department1.setAddr("beijing");
        department1.setSuperior("小强");
        final String depJsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(department1);
        System.out.println(depJsonStr);
        /*
        {
            "depName" : "QA",
            "addr" : "beijing",
            "superior" : "小强"
        }
        */
    }
    

      

      

  • 相关阅读:
    控件的用法ComboBox;RadionButton;Timer;DataGridView
    echo.js实现图片延迟加载,
    取消移动端a标签点击变色
    JS实现上传图片实时预览
    Myeclipse6.0安装svn插件
    警告: Parameters: Character decoding failed. Parameter skipped
    jsp到action 传递url时中文出现乱码
    java面试题
    myeclipse中hibernate出错
    java中abstract的用法
  • 原文地址:https://www.cnblogs.com/-beyond/p/11640577.html
Copyright © 2020-2023  润新知