一文掌握Jackson基础到高级用法

437 阅读4分钟

基本依赖

plugins {
    id 'java'
}
java {
    version = JavaVersion.VERSION_17
}
group = 'cn.mj'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation('com.fasterxml.jackson.core:jackson-databind:2.17.1')
    // xml使用
    implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.17.1")
}
test {
    useJUnitPlatform()
}

基本配置

public class JacksonTest {
    private static ObjectMapper mapper;
    private static XmlMapper xmlMapper;

    @BeforeAll
    public static void config() {
        mapper = new ObjectMapper();
        // 序列化配置
        // 打印的时候美化输出
//        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 允许序列化空对象
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁止序列化 java.util.Date, Calendar 为时间戳
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        // 反序列化配置

        // 禁止 在反序列化遇到不认识字段时报错
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 禁止 输出 空 String为null
        mapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

        xmlMapper = new XmlMapper();

        // 序列化配置
        // 打印的时候美化输出
//        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 允许序列化空对象
        xmlMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁止序列化 java.util.Date, Calendar 为时间戳
        xmlMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        // 反序列化配置

        // 禁止 在反序列化遇到不认识字段时报错
        xmlMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 禁止 输出 空 String为null
        xmlMapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    }
}

基本用例

简单序列号

    public void simpleSerializeTest() throws JsonProcessingException {
        var stu = new Student("Jonny",123);
        var json = mapper.writeValueAsString(stu);
        System.out.println(json);
    }

简单反序列化

    public void simpleDeserializeTest() throws JsonProcessingException {
        var json = """
                {"name":"Jonny","age":123}
                """;
        var stu = mapper.readValue(json, Student.class);
        System.out.println(stu);
    }

反序列化忽略未知字段

public class Student {
    private String name;
    private int age;
    // getter、setter
}
    public void deserializeWithUnknownFields() throws JsonProcessingException {
        var json = """
                {"name":"Jonny","age":123,"gender":"Male"}
                """;
        var stu = mapper.readValue(json, Student.class);
        System.out.println(stu);
    }

反序列化泛型容器

    public void deserializeWithGenerics() throws JsonProcessingException {
        var json = """
                [{"name":"Jonny","age":123,"gender":"Male"},{"name":"Jonny","age":123,"gender":"Male1"}]
                """;
        var stu = mapper.readValue(json, new TypeReference<List<Student>>(){ });
        System.out.println(stu);
    }

多态反序列化(高端操作)

一定可以区分不同的子类

//@JsonTypeInfo(use=DEDUCTION) // Include Java class simple-name as JSON property "type"
@JsonTypeInfo(use= Id.DEDUCTION)
@JsonSubTypes({@JsonSubTypes.Type(SleepEvent.class), @JsonSubTypes.Type(TravelEvent.class)})
public abstract class IEvent {
    public abstract void showInfo();
}

public class SleepEvent extends IEvent{
    private String name;
    private Integer hour;
}
public class TravelEvent extends IEvent{
    private String name;
    private String address;
}
    public void deserializeWithPolymorphicTypes() throws JsonProcessingException {
        var json = """
                [
                {"name":"jonny","hour":10},
                {"name":"jonny","address":"sichuan"}
                ]
                
                """;
        var events = mapper.readValue(json, new TypeReference<List<IEvent>>(){});
        events.forEach(IEvent::showInfo);
    }

将json里的字段序列化json里:平级

public class ExtensionBean {
    private String name;
    private Map<String, Object> params;


    public String getName() {
        return name;
    }
    @JsonAnyGetter
    public Map<String, Object> getParams() {
        return params;
    }
}
    public void serializeWithJsonAnyGetter() throws JsonProcessingException {
        var bean = new ExtensionBean();
        bean.setName("jonny");
        var params = new HashMap<String, Object>();
        params.put("age", 18);
        params.put("gender", "Male");
        bean.setParams(params);
        var json = mapper.writeValueAsString(bean);
        System.out.println(json);
    }

通过JsonGetter指定字段序列化的getter方法

    public void serializeWithJsonGetter() throws JsonProcessingException {
        var task = new Task();
        task.setName("http");
        task.setStatus(TaskStatus.NEW);
        task.setExecuteStatus(2);
        var json = mapper.writeValueAsString(task);
        System.out.println(json);
    }

序列化时直接将json字符串作为json的一部分:子节点

public class RawBean {
    private String name;
    @JsonRawValue
    private String json;
}
    public void serializeWithJsonRawValue() throws JsonProcessingException {
        var json = """
                {"age":19,"gender":"male"}
                """;
        var bean = new RawBean();
        bean.setJson(json);
        bean.setName("jonny");
        json = mapper.writeValueAsString(bean);
        System.out.println(json);
    }

通过JsonValue指定对象序列化时的取值:枚举

public enum TaskStatus {
    NEW(0,"new"),
    EXECUTING(1,"executing"),
    SUCCESS(2,"success"),
    FAIL(3,"fail"),
    CANCEL(4,"cancel"),
    ;


    private final int code;
    private final String desc;

    @JsonValue
    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }
    private TaskStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
}
    public void serializeWithJsonValue() throws JsonProcessingException {
        var task = new Task();
        task.setName("http");
        task.setStatus(TaskStatus.NEW);
        task.setExecuteStatus(2);
        var json = mapper.writeValueAsString(task);
        System.out.println(json);
    }

使用JsonSerialize使用自定义序列化器

@JsonSerialize(using = CustomSerialize.class)
public class Wrapper <T>{
    private Integer  code;
    private T data;
    private String msg;
}
public class CustomSerialize extends StdSerializer<Wrapper> {
    @Serial
    private static final long serialVersionUID = 3779575481664073505L;

    protected CustomSerialize(Class<Wrapper> t) {
        super(t);
    }
    protected CustomSerialize() {
        this(null);
    }

    @Override
    public void serialize(Wrapper wrapper, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        Class<? extends Wrapper> aClass = wrapper.getClass();
        jsonGenerator.writePOJO(wrapper);

    }
}
    public void serializeWithCustomSerialization() throws JsonProcessingException {
        var wrapper = new Wrapper<>();
        wrapper.setCode(200);
        wrapper.setMsg("success");
        wrapper.setData(new Student("jonny", 18));
        var json = mapper.writeValueAsString(wrapper);
        System.out.println(json);
    }

通过配置WRAP_ROOT_VALUE在序列化的时候再包一层

    public void serializeWithJsonRoomName() throws JsonProcessingException {
        var stu = new Student("jonny", 18);
        mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        var json = mapper.writeValueAsString(stu);
        System.out.println(json);
    }
@JsonRootName(value = "student")
public class Student {
    //...
}

使用JsonCreator来指定反序列化时使用的构造函数、工厂方法

    public void deserializeWithJsonCreator() throws JsonProcessingException {
        var json = """
                {"name":"jonny","age":18}
                """;
        var stu = mapper.readValue(json, Student.class);
        System.out.println(stu);
    }
public class Student {
    @JsonCreator
    public Student(
            @JsonProperty("name") String name,
            @JsonProperty("age") int age) {
        this.name = name;
        this.age = age;
        System.out.println("use this constructor");
    }
}

使用JacksonInject实现反序列化时使用外部的值

  1. 在pojo指定需要注入字段的名称
  2. 在InjectableValues进行配置
  3. 反序列化
    public void deserializeWithJacksonInject () throws JsonProcessingException {
       var user = "jonny";
       var json = """
               {"age":18}
               """;
        InjectableValues injectableValues = new InjectableValues.Std().addValue("name",user);
        var stu = mapper.reader(injectableValues).forType(Student.class).readValue(json);
        System.out.println(stu);
    }
public class Student {
    @JacksonInject(value = "name")
    private String name;
    private int age;
}

使用JsonAnySetter实现在反序列化的时候已知字段序列化,未知字段放map

    public void deserializeWithJsonAnySetter() throws JsonProcessingException {
        var json = """
                {"name":"jonny","age":18,"gender":"male"}
                """;
        var bean = mapper.readValue(json, ExtensionBean.class);
        System.out.println(bean);
    }
public class ExtensionBean {
    private String name;
    private Map<String, Object> params;
    @JsonAnySetter
    public void add(String key, Object value){
        if (params == null){
            params = new java.util.HashMap<>();
        }
        params.put(key, value);
    }
}

通过JsonSetter指定反序列化时字段的setter方法

    public void deserializeWithJsonSetter() throws JsonProcessingException {
        var json = """
                {"name":"jonny","age":18}
                """;
        var stu = mapper.readValue(json, Student.class);
    }
public class Student {
    private String name;
    private int age;
    @JsonSetter("age")
    public void setAgeSpecial(int age) {
        this.age = age;
        System.out.println("use special age setter");
    }
}

通过JsonAlias指定反序列化别名

    public void deserializeWithJsonAlias()  throws JsonProcessingException {
        var json = """
                {"Name":"jonny","age":18}
                """;
        var bean = mapper.readValue(json, AliasBean.class);
        System.out.println(bean);
    }
public class AliasBean {
    @JsonAlias({"Name","NAME"})
    private String name;
}

JsonIgnoreProperties 设置序列化、反序列化忽略的字段

JsonIgnore 设置序列化、反序列化忽略的字段,直接标注字段上

JsonIgnoreType 设置序列化、反序列化忽略的类型

JsonInclude 扩展序列化时忽略空字段

JsonProperty 指定字段在序列化、反序列化时的名称

JsonFormat 指定序列化日期格式化(注意配置时区)

直接序列化为xml

    public void serializeToXml() throws JsonProcessingException {
        var bean = new MyBean(1,"Jonny");
        var json = xmlMapper.writeValueAsString(bean);
        System.out.println(json);
    }