Jackson serialization and deserialization application practice

Prepare serialized objects
. Two classes are prepared, teacher class and student class. One student has only one teacher.
The constructor and setter and getter methods are omitted here.

Teacher.java

public class Teacher {
private String name;
private Integer age;
}
Student.java

package org.zwx;

public class Student {
private String name;
private Integer age;
private Sex sex;
private String fatherName;
private Date bornTime;
private Teacher teacher;
}
Sex.java

public enum Sex { MALE("男"), FEMALE("女");

private String name;

Sex(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

}
4 Introduce jackson dependency
This example is based on gradle, jackson-databind version 2.11.2 is selected from the maven central warehouse

compile group:'com.fasterxml.jackson.core', name:'jackson-databind', version: '2.11.2'
5 Serialization and formatting output
5.1 The process
first needs an object to be serialized, in this example The student object
creates an object mapper, and the ObjectMapper under the jackson package
calls the serialization function. In this example, writeValueAsString converts the object to a string, which is convenient for displaying the
5.2 code
public void testSerializable() throws IOException { Student student1 = new Student(" Xiao Ming", 18, Sex.MALE, "Wang Fugui", new Date(), new Teacher("李老师", 40)); Student student2 = new Student("小花", 16, Sex.FEMALE, "A lot of money ”, new Date(), new Teacher("赵老师", 38)); List students = new ArrayList<>(); students.add(student1); students.add(student2);




ObjectMapper mapper = new ObjectMapper();
String s = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(students);
System.out.println(s);

}
5.3 Results
[{ "name": "Xiao Ming", "age": 18, "sex": "MALE", "fatherName": "王富贵" , "bornTime": 1599996926917, "teacher": { "name" : "Mr. Li", "age": 40 } }, { "name": "小花", "age": 16, "sex": "FEMALE", "fatherName": "A lot of money", "bornTime": 1599996926917, "teacher": { "name": "Mr. Zhao", "age": 38 } }] 5.4 Analysis The method writerWithDefaultPrettyPrinter is called in the example, which beautifies the json format






















Otherwise it will print [{"name":"Xiaoming","age":18,"sex":"MALE","fatherName":"Wang Fugui","bornTime":1599997061097,"teacher":{"name" :"Mr. Li","age":40}},{"name":"小花","age":16,"sex":"FEMALE","fatherName":"a lot of money","bornTime": 1599997061097,"teacher":{"name":"赵老师","age":38}}]
6 Customize the serialized name
6.1 Scenario
If you need to change the serialized json from hump name to underscore name, such as fatherName Modify to father_name

Only need to use the annotation JsonProperty configuration on the field fatherName

6.2 Sample code
@JsonProperty(“father_name”)
private String fatherName;
@JsonProperty(“born_time”)
private Date bornTime;
6.3 Sample result
[{ “name”: “小明”, “age”: 18, “sex”: “MALE ", "teacher": { "name": "Mr. Li", "age": 40 }, "father_name": "Wang Fugui", "born_time": 1599997157609 }, { "name": " 小花", "age ": 16, "sex": "FEMALE", "teacher": { "name": "Mr. Zhao", "age": 38 }, "father_name": "A lot of money", "born_time": 1599997157610 }] 7 Custom output format 7.1 bornTime format setting






















The current bornTime format is unix time stamp, which is very poorly readable

Now modify it to yyyy-MM-dd HH:mm:ss
and set the time zone to Dongba District

Sample code

@JsonProperty(“born_time”)
@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)
private Date bornTime;
结果

[{ "Name": "小明", "age": 18, "sex": "MALE", "teacher": { "name": "Mr. Li", "age": 40 }, "father_name": " "Wang Fugui", "born_time": "2020-09-13 19:50:47" }, { "name": " 小花" , "age": 16, "sex": "FEMALE", "teacher": { “Name”: “Mr. Zhao”, “age”: 38 }, “father_name”: “a lot of money”, “born_time”: “2020-09-13 19:50:47” }] 7.2 Only need to set sex to Chinese Add a method getOrdinal for Sex, and add the annotation JsonValue





















Sample code

@JsonValue
public String getOrdinal() { return name; } Sample result


[{ "Name": "小明", "age": 18, "sex": "男", "teacher": { "name": "Mr. Li", "age": 40 }, "father_name": " Wang Fugui", "born_time": "2020-09-13 19:57:47" }, { "name": " 小花" , "age": 16, "sex": "女", "teacher": { "Name": "Ms. Zhao", "age": 38 }, "father_name": "a lot of money", "born_time": "2020-09-13 19:57:47" }] 7.3 Sex is set as a serial number for some scenes I like to set men and women with serial numbers such as 0 and 1, that is, the serial number of the enumeration: 0 means male, 1 means female





















At this time, you need to modify the getOrdinal method of Set

Modify the return value type to int to
call the getOrdinal method of the parent class
Sample code

@JsonValue
public int getOrdinal() { return super.ordinal(); } Sample result


[{ "Name": "Xiaoming", "age": 18, "sex": 0, "teacher": { "name": "Mr. Li", "age": 40 }, "father_name": "Wang Fugui ", "born_time": "2020-09-13 20:01:44" }, { "name": " 小花" , "age": 16, "sex": 1, "teacher": { "name": "Mr. Zhao", "age": 38 }, "father_name": "a lot of money", "born_time": "2020-09-13 20:01:44" }] 8 Pacing the nested type The scene is as mentioned above The results show that the two attributes of teacher are not in the first layer of student, and sometimes they may be deeper, which is not friendly to use























How to use the two attributes teacher_name and teacher_age instead of teacher?

Add the annotation JsonUnwrapped to the teacher attribute of the Student, which means not to wrap
. Use the annotation JsonProperty to rename the attribute of the Teacher.
Sample code
Student.java

@JsonUnwrapped
private Teacher teacher;
Teacher.java

@JsonProperty(“teacher_name”)
private String name;
@JsonProperty(“teacher_age”)
private Integer age;
Example result
[{ “name”: “小明”, “age”: 18, “sex”: 0, “teacher_name”: "Teacher Li", "teacher_age": 40, "father_name": "Wang Fugui", "born_time": "2020-09-13 20:21:53" }, { "name": " 小花", "age" : 16, "sex": 1, "teacher_name": "Mr. Zhao", "teacher_age": 38, "father_name": "a lot of money", "born_time": "2020-09-13 20:21:53" } ] 9 Custom serializer 9.1 Scenario If you need to adjust the age to the theoretical school age, that is, subtract 7 from the age to get the theoretical school age, how to do it?


















Create a custom age serializer AgeSerializer, inherit StdSerializer<>
Create the construction method of AgeSerializer
Rewrite the serialize function
Use annotations to fix the serializer AgeSerializer that specifies the Student attribute age
9.2 Sample code
AgeSerializer.java

public class AgeSerializer extends StdSerializer {
protected AgeSerializer() {
super(Integer.class);
}

@Override
public void serialize(Integer value, JsonGenerator gen, SerializerProvider provider) throws IOException {
    gen.writeNumber(value - 7);
}

}
Student.java

@JsonSerialize(using = AgeSerializer.class)
private Integer age;
9.3 Example result
[{ "name": "小明", "age": 11, "sex": 0, "teacher_name": "李老师", "teacher_age" : 40, "father_name": "Wang Fugui", "born_time": "2020-09-13 20:31:59" }, { "name": " 小花", "age": 9, "sex": 1 , “Teacher_name”: “Teacher Zhao”, “teacher_age”: 38, “father_name”: “a lot of money”, “born_time”: “2020-09-13 20:31:59” }] 10 Deserialization 10.1 Process first Need to have serialized data, which can be string, byte[], file binary, etc. Create an object mapper, ObjectMapper under the jackson package calls the deserialization function, readValue in this example, converts the string to an object 10.2 Anti Serialize object data






















Sample code

public void testDeserializable() throws JsonProcessingException {
String s = “{“name”:“小明”,“age”:11,“sex”:0,“teacher_name”:“李老师”,“teacher_age”:40,“father_name”:“王富贵”,“born_time”:“2020-09-13 20:46:10”}”;
ObjectMapper mapper = new ObjectMapper();
Student student = mapper.readValue(s, Student.class);
System.out.println(student);
}
示例结果

Student{name='小明', age=11, sex=MALE, fatherName='王富贵', bornTime=Sun Sep 13 20:46:10 CST 2020, teacher=Teacher{name='李老师', age=40 }}
Analysis

In order to facilitate the printing of the object data, the toString method of Student and Teacher is rewritten
. It can be seen from the data that the result of age is wrong. The reason is that the previous custom serializer reduces the age by 7, and Section 10.4 will pass. Custom deserializer to solve this problem
10.3 Deserialize object array data
Sample code

public void testDeserializableStudents() throws JsonProcessingException { String s = "[{"name":"小明","age":11,"sex":0,"teacher_name":"Teacher Li","teacher_age":40," father_name":"Wang Fugui","born_time":"2020-09-13 20:51:31"},{"name":"小花","age":9,"sex":1,"teacher_name" :"Teacher Zhao","teacher_age":38,"father_name":"a lot of money","born_time":"2020-09-13 20:51:31"}]"; ObjectMapper mapper = new ObjectMapper(); Student [] students = mapper.readValue(s, Student[].class); for (Student student: students) { System.out.println(student); } } Sample results







Student{name='小明', age=11, sex=MALE, fatherName='王富贵', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='李老师', age=40 }}
Student{name='小花', age=9, sex=FEMALE, fatherName='a lot of money', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='赵老师', age =38}}
Analysis

The second parameter of readValue needs to pass the type. It is recommended to use an array here, but not to use List. The specific reason is that I have not spent the time to study
10.4 custom deserializers
. It can be seen from the phenomenon in section 10.2 and 10.3, only The custom serializer will cause the serialization process to be normal, and the deserialization process is still the default logic, which sometimes leads to unexpected results

In this scenario, you can consider a custom deserializer

Create a custom deserializer AgeDeserializer, inherit StdDeserializer<>
override the deserialize method
, add the annotation JsonDeserialize to the student's age attribute, and specify the deserializer AgeDeserializer
sample code

AgeDeserializer.java

public class AgeDeserializer extends JsonDeserializer {
@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return p.getIntValue() + 7;
}
}
Student.java

@JsonSerialize(using = AgeSerializer.class)
@JsonDeserialize(using = AgeDeserializer.class)
private Integer age;
示例结果

Student{name='小明', age=18, sex=MALE, fatherName='王富贵', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='李老师', age=40 }}
Student{name='小花', age=16, sex=FEMALE, fatherName='a lot of money', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='赵老师', age =38}}
11 Annotation JsonInclude
This annotation is used on the entity class, format @JsonInclude(value = JsonInclude.Include.NON_DEFAULT)

Among them, Include has 7 parameters, and the function comparison is as follows

Parameter function note
Include.ALWAYS property is always serialized (get method is required) The default value
Include.NON_DEFAULT property is the default value is not serialized, such as: int:0, bool:false
Include.NON_EMPTY property is empty ("") or null Do not serialize
Include.NON_NULL The attribute is null Do not serialize
Include.CUSTOM
Include.USE_DEFAULTS
Include.NON_ABSENT
code example
Student.java

@JsonInclude(value = JsonInclude.Include.NON_DEFAULT)
public class Student {
public void testNonDefault() throws IOException {
Student student = new Student("", 0, null, null, null, null);
ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(student);
System.out.println(s);
}
示例输出
{
“name” : “”,
“age” : -7
}
分析
龙华大道1号http://www.kinghill.cn/LongHuaDaDao1Hao/index.html

Guess you like

Origin blog.csdn.net/weixin_45032957/article/details/108575263