Jackson 快速入门

作者 | 2020年3月18日

Jackson提供了writeValue()readValue()方法用于实现JSON与Java对象的双向转换。

Java对象转JSON:

ObjectMapper mapper = new ObjectMapper();

// 把对象转为json文件
mapper.writeValue(new File("c:\\test\\staff.json"), new Staff());

// 把对象转为json字符串
String jsonString = mapper.writeValueAsString(new Staff());

// 格式化输出
String jsonString2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new Staff());

JSON转Java对象:

ObjectMapper mapper = new ObjectMapper();

// JSON文件转对象
Staff obj = mapper.readValue(new File("c:\\test\\staff.json"), Staff.class);

// 转换在线的JSON文件为对象
Staff obj = mapper.readValue(new URL("http://some-domains/api/staff.json"), Staff.class);

// 转换JSON字符串为对象
Staff obj = mapper.readValue("{'name' : 'myexample'}", Staff.class);

注意:下面的例子使用Jackson 2.9.8

例子1: 下载Jackson

pom.xml文件中声明jackson-databind的依赖,该依赖会同时引入jackson-annotationsjackson-core

pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

查看依赖关系:

$ mvn dependency:tree

\- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO]    \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile

先来写一个简单的POJO对象给后面的例子使用。

Staff.java

public class Staff {

    private String name;
    private int age;
    private String[] position;              //  Array
    private List<String> skills;            //  List
    private Map<String, BigDecimal> salary; //  Map

    // 省略get/set方法
}

例子2: 转换Java对象为JSON

JacksonExample1.java

package cc.myexample;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class JacksonExample1 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = createStaff();

        try {

            // 转换Java对象为JSON文件
            mapper.writeValue(new File("c:\\test\\staff.json"), staff);

            // 转换Java对象为JSON字符串
            String jsonString = mapper.writeValueAsString(staff);

            System.out.println(jsonString);

            // 格式化输出
            String jsonInString2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);

            System.out.println(jsonInString2);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static Staff createStaff() {

        Staff staff = new Staff();

        staff.setName("myexample");
        staff.setAge(38);
        staff.setPosition(new String[]{"Founder""CTO""Writer"});
        Map<String, BigDecimal> salary = new HashMap() {{
            put("2010"new BigDecimal(10000));
            put("2012"new BigDecimal(12000));
            put("2018"new BigDecimal(14000));
        }};
        staff.setSalary(salary);
        staff.setSkills(Arrays.asList("java""python""node""kotlin"));

        return staff;

    }

}

输出

c:\test\staff.json

{"name":"myexample","age":38,"position":["Founder","CTO","Writer"],"skills":["java","python","node","kotlin"],"salary":{"2018":14000,"2012":12000,"2010":10000}}

终端

{"name":"myexample","age":38,"position":["Founder","CTO","Writer"],"skills":["java","python","node","kotlin"],"salary":{"2018":14000,"2012":12000,"2010":10000}}

{
  "name" : "myexample",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "skills" : [ "java", "python", "node", "kotlin" ],
  "salary" : {
    "2018" : 14000,
    "2012" : 12000,
    "2010" : 10000
  }
}

例子3: 转换JSON为Java对象

JacksonExample2.java

package cc.myexample;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonExample2 {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        try {

            // JSON文件转Java对象
            Staff staff = mapper.readValue(new File("c:\\test\\staff.json"), Staff.class);

            // JSON文件转Java对象
            String jsonInString = "{\"name\":\"myexample\",\"age\":37,\"skills\":[\"java\",\"python\"]}";
            Staff staff2 = mapper.readValue(jsonInString, Staff.class);

            // 直接输出
            System.out.println(staff2);

            // 格式化输出
            String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff2);

            System.out.println(prettyStaff1);


        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

输出

Staff{name='myexample', age=37, position=null, skills=[java, python], salary=null}

{
  "name" : "myexample",
  "age" : 37,
  "position" : null,
  "skills" : [ "java""python" ],
  "salary" : null
}

例子4: 使用注解@JsonProperty

默认情况下,JSON中的属性名与对象中的属性名保持一致,比如:

public class Staff {
    private String name;
    private int age;

    // ...
}

转换为JSON后输出:

{"name":"abc""age":38}

通过使用注解@JsonProperty则可以改变属性的名称:

public class Staff {
    @JsonProperty("custom_name")
    private String name;
    private int age;

    // ...
}

输出

{"custom_name":"abc""age":38}

例子5: 屏蔽值为null的字段

默认情况下,Jackson会输出值为null的字段:

{
  "name" : "myexample",
  "age" : 38,
  "position" : null,
  "skills" : null,
  "salary" : null
}

通过使用注解@JsonInclude可以改变这个行为。

在类上面使用@JsonInclude注解:

Staff.java

import com.fasterxml.jackson.annotation.JsonInclude;

// 只把有值的字段进行转换
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Staff {

    private String name;
    private int age;
    private String[] position;              
    private List<String> skills;           
    private Map<String, BigDecimal> salary; 
    //...
}

在字段上面使用@JsonInclude注解:

Staff.java

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Staff {

    private String name;
    private int age;
    // 如果position字段的值不是null,则转换它
    private String[] position;              
    private List<String> skills;           
    private Map<String, BigDecimal> salary; 
    //...
}

输出

{
  "name" : "myexample",
  "age" : 38,
  "skill" : null,
  "salary" : null
}

除了使用@JsonInclude注解之外,还可以在ObjectMapper上面进行进行全局的配置:

    ObjectMapper mapper = new ObjectMapper();

    // 全局配置,忽略所有值为null的字段
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

例子7: @JsonView

注解@JsonView可以用于设置字段的可见性,让不同的用户看到的字段不一样。

CompanyViews.java

package cc.myexample;

public class CompanyViews {

    public static class Normal{};

    public static class Manager extends Normal{};

}

普通用户只能看见雇员的姓名与年龄,经理可以看见所以字段。

Staff.java

import com.fasterxml.jackson.annotation.JsonView;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Staff {

    @JsonView(CompanyViews.Normal.class)
    private String name;

    @JsonView(CompanyViews.Normal.class)
    private int age;

    @JsonView(CompanyViews.Manager.class)
    private String[] position;

    @JsonView(CompanyViews.Manager.class)
    private List<String> skills;

    @JsonView(CompanyViews.Manager.class)
    private Map<String, BigDecimal> salary;

    // 省略get/set函数
}

JacksonExample.java

package cc.myexample;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class JacksonExample {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        Staff staff = createStaff();

        try {

            // 启用格式化输出
            mapper.enable(SerializationFeature.INDENT_OUTPUT);

            // 普通用户看到的JSON
            String normalView = mapper
                .writerWithView(CompanyViews.Normal.class)
                .writeValueAsString(staff);

            System.out.format("Normal views\n%s\n", normalView);

            // 经理看到的JSON
            String managerView = mapper
                .writerWithView(CompanyViews.Manager.class)
                .writeValueAsString(staff);

            System.out.format("Manager views\n%s\n", managerView);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static Staff createStaff() {

        Staff staff = new Staff();

        staff.setName("myexample");
        staff.setAge(38);
        staff.setPosition(new String[]{"Founder""CTO""Writer"});
        Map<String, BigDecimal> salary = new HashMap() {{
            put("2010"new BigDecimal(10000));
            put("2012"new BigDecimal(12000));
            put("2018"new BigDecimal(14000));
        }};
        staff.setSalary(salary);
        staff.setSkills(Arrays.asList("java""python""node""kotlin"));

        return staff;

    }

}

输出

Normal views
{
  "name" : "myexample",
  "age" : 38
}

Manager views
{
  "name" : "myexample",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ],
  "skills" : [ "java", "python", "node", "kotlin" ],
  "salary" : {
    "2018" : 14000,
    "2012" : 12000,
    "2010" : 10000
  }
}

例子8: @JsonIgnore合@JsonIgnoreProperties

默认情况下Jackson会把所有字段全部转为JSON(包括static字段)。

使用@JsonIgnore注解标注一个字段,可以使该字段在转换为JSON时被忽略。

import com.fasterxml.jackson.annotation.JsonIgnore;

public class Staff {

    private String name;
    private int age;
    private String[] position;

    @JsonIgnore
    private List<String> skills;

    @JsonIgnore
    private Map<String, BigDecimal> salary;

    // 省略get/set方法
}

输出

{
  "name" : "myexample",
  "age" : 38,
  "position" : [ "Founder", "CTO", "Writer" ]
}

在类上使用@JsonIgnoreProperties注解可以忽略多个字段。

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties({"salary""position"})
public class Staff {

    private String name;
    private int age;
    private String[] position;
    private List<String> skills;
    private Map<String, BigDecimal> salary;
    // 省略get/set方法
}

输出

{
  "name" : "myexample",
  "age" : 38,
  "skills" : [ "java""python""node""kotlin" ]
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注