文章目录
1 简单介绍
Jackson 是用来序列化和反序列化 json 的 Java 的开源框架。Spring MVC 的默认 json 解析器便是 Jackson。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。
Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson
ackson 的核心模块由三部分组成。
-
jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。
-
jackson-annotations,注解包,提供标准注解功能;
-
jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。
若想在 Java 代码中使用 Jackson 的核心模块的 jar 包 ,需要在 pom.xml 中添加如下信息。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10</version>
</dependency>
说明
jackson-databind 依赖 jackson-core 和 jackson-annotations,当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中。在添加相关依赖包之后,就可以使用 Jackson。
2 快速入门
2.0 准备工作
- 新建一个maven工程json-study
- 导入依赖
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13-beta-3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.22</version>
</dependency>
</dependencies>
- 准备一个model
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private Integer age;
private Date date;
private int height;
private List<String> course;
// 班主任,
private Teacher teacher;
}
@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private String name;
}
2.1 序列化
简单使用
/**
* 测试序列化
* @throws JsonProcessingException
*/
@Test
public void test01() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Student student = build();
String json = objectMapper.writeValueAsString(student);
System.out.println(json);
}
private Student build() {
return Student.builder()
.age(18)
.date(new Date())
.height(100)
.course(Arrays.asList("Math","English","Chinese"))
.teacher(Teacher.builder().name("张老师").build())
.name("Jackson").build();
}
输出
{"name":"Jackson","age":18,"date":1603263016919,"height":100,"course":["Math","English","Chinese"],"teacher":{"name":"张老师"}}
格式化json
@Test
public void test02() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Student student = build();
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(json);
}
输出
{
"name" : "Jackson",
"age" : 18,
"date" : 1603263150974,
"height" : 100,
"course" : [ "Math", "English", "Chinese" ],
"teacher" : {
"name" : "张老师"
}
}
2.2 反序列化
/***
* 测试反序列化
* @return
*/
@Test
public void test03() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Student student = build();
// 先序列化
String json = objectMapper.writeValueAsString(student);
//String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
// 反序列化
Student studentFromJson = objectMapper.readValue(json, Student.class);
System.out.println(studentFromJson);
}
2.3 总结
ObjectMapper
通过 writeValue
系列方法将 java 对象序列化为 json,并将 json 存储成不同的格式,·String·,ByteArray
,Writer
, File
,OutStream
和 DataOutput
。
ObjectMapper
通过readValue
系列方法从不同的数据源像 String
, Byte Array
, Reader
,File
,URL
, InputStream
将 json 反序列化为 java 对象。
3 ObjectMapper配置
在调用 writeValue 或调用 readValue 方法之前,往往需要设置 ObjectMapper 的相关配置信息。这些配置信息应用 java 对象的所有属性上。示例如下:
//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//在序列化时自定义时间日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//在序列化时忽略值为 null 的属性
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//在序列化时忽略值为默认值的属性
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
更多配置信息可以查看 Jackson 的 DeserializationFeature,SerializationFeature 和 Include。
3.1 演示
测试刚刚上面的几个配置
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
- 不忽略,默认也是不忽略
public ObjectMapper objectMapper = new ObjectMapper();
@Test
public void test01() throws IOException {
// 在反序列化时不忽略在 json 中存在但 Java 对象不存在的属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,true);
//Teacher 中没有age属性
String json = "{\n" +
" \"name\": \"张老师\",\n" +
" \"age\": 40\n" +
"}";
Teacher teacher = objectMapper.readValue(json, Teacher.class);
System.out.println(teacher);
}
默认就是true,不会忽略在 json 中存在但 Java 对象不存在的属性,这时候在反序列化的时候就会报错
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "age" (class study.wyy.json.study.jackson.model.Teacher), not marked as ignorable (one known property: "name"])
at [Source: (String)"{
"name": "张老师",
"age": 40
}"; line: 3, column: 12] (through reference chain: study.wyy.json.study.jackson.model.Teacher["age"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:823)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1153)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
at study.wyy.json.study.jackson.demo.ConfigObjectMapper.test01(ConfigObjectMapper.java:29)
- 设置为忽略
@Test
public void test02() throws IOException {
// 在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
//language=JSON
String json = "{\n" +
" \"name\": \"张老师\",\n" +
" \"age\": 40\n" +
"}";
Teacher teacher = objectMapper.readValue(json, Teacher.class);
System.out.println(teacher);
}
Teacher(name=张老师)
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
在序列化时日期是否以时间戳的形式,默认是true,可参考快速入门例子
@Test
public void test03() throws IOException {
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Student student = build();
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(value);
}
{
"name" : "Jackson",
"age" : 18,
"date" : "2020-10-21T08:11:01.584+0000",
"height" : 100,
"course" : [ "Math", "English", "Chinese" ],
"teacher" : {
"name" : "张老师"
}
}
在序列化时自定义时间日期格式
在序列化时日期是否以时间戳的形式为false时候,默认是2020-10-21T08:11:01.584+0000
如何自定义呢
/**
* 自定义时间序列化格式
* @throws IOException
*/
@Test
public void test04() throws IOException {
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
Student student = build();
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(value);
}
{
"name" : "Jackson",
"age" : 18,
"date" : "2020/10/21 16:26:14",
"height" : 100,
"course" : [ "Math", "English", "Chinese" ],
"teacher" : {
"name" : "张老师"
}
}
在序列化时忽略值为 null 的属性
@Test
public void test05() throws IOException {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Student student = build();
student.setAge(null);
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(value);
}
{
"name" : "Jackson",
"date" : 1603269862759,
"height" : 100,
"course" : [ "Math", "English", "Chinese" ],
"teacher" : {
"name" : "张老师"
}
}
在序列化时忽略值为默认值的属性
- 先不忽略
@Test
public void test06() throws IOException {
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
Student student = Student.builder()
.name("jackson")
.date(new Date())
.age(18)
.build();
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(value);
}
{
"name" : "jackson",
"age" : 18,
"date" : 1603270077300,
"height" : 0,
"course" : null,
"teacher" : null
}
- 设置忽略
@Test
public void test06() throws IOException {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
Student student = Student.builder()
.name("jackson")
.date(new Date())
.age(18)
.build();
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(value);
}
{
"name" : "jackson",
"age" : 18,
"date" : 1603270133718
}
那些没有设置的属性,这里就没有序列化。
3.2 补充一些其他配置
// 美化输出
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 允许序列化空的POJO类
// (否则会抛出异常)
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);
// 强制JSON 空字符串("")转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
// 在JSON中允许C/C++ 样式的注释(非标准,默认禁用)
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许没有引号的字段名(非标准)
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号(非标准)
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 强制转义非ASCII字符
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
// 将内容包裹为一个JSON属性,属性名由@JsonRootName注解指定
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
4 用注解管理映射
准备一个模型
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class StudentWithAnnotations {
private String name;
private Integer age;
private Date date;
private int height;
@JsonIgnore
private List<String> course;
// 班主任,
private Teacher teacher;
}
4.1 JsonIgnore
可用于字段、getter/setter、构造函数参数上,作用相同,都会对相应的字段产生影响。使相应字段不参与序列化和反序列化。
- course设置了
@JsonIgnore
注解,序列化的时候会忽略这个字段
public ObjectMapper objectMapper = new ObjectMapper();
/**
* 测试忽略,
* @throws IOException
*/
@Test
public void testJsonIgnore() throws IOException {
StudentWithAnnotations student = buildStudentWithAnnotations();
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(json);
}
public StudentWithAnnotations buildStudentWithAnnotations() {
return StudentWithAnnotations.builder()
.age(18)
.date(new Date())
.height(100)
.course(Arrays.asList("Math","English","Chinese"))
.teacher(Teacher.builder().name("张老师").build())
.name("Jackson").build();
}
输出
{
"name" : "Jackson",
"age" : 18,
"date" : 1603271223291,
"height" : 100,
"teacher" : {
"name" : "张老师"
}
}
那发序列化的时候呢
/***
* 测试反序列化
* @return
*/
@Test
public void testJsonIgnore2() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Student student = build();
// 先序列化
String json = objectMapper.writeValueAsString(student);
System.out.println();
// 反序列化
StudentWithAnnotations studentFromJson = objectMapper.readValue(json, StudentWithAnnotations.class);
System.out.println(studentFromJson);
}
输出:course也是null,也会忽略
StudentWithAnnotations(name=Jackson, age=18, date=Wed Oct 21 17:10:18 CST 2020, height=100, course=null, teacher=Teacher(name=张老师))
4.2 @JsonProperty
用于属性,把属性的名称序列化时转换为另外一个名称。
@JsonProperty("firstName")
private String name;
@Test
public void testJsonProperty() throws IOException {
StudentWithAnnotations student = buildStudentWithAnnotations();
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(json);
}
输出: name属性在序列化json的时候,变成了firstName
{
"age" : 18,
"date" : 1603272038044,
"height" : 100,
"teacher" : {
"name" : "张老师"
},
"firstName" : "Jackson"
}
反序列化
/***
* 测试反序列化
* @return
*/
@Test
public void testJsonProperty2() throws IOException {
StudentWithAnnotations student = buildStudentWithAnnotations();
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
// 反序列化
StudentWithAnnotations studentFromJson = objectMapper.readValue(json, StudentWithAnnotations.class);
System.out.println(studentFromJson);
}
输出:同一json字符串中的firstName也是可以映射到name属性的
StudentWithAnnotations(name=Jackson, age=18, date=Wed Oct 21 17:22:55 CST 2020, height=100, course=null, teacher=Teacher(name=张老师))
4.3 JsonFormat
用于属性或者方法,把属性的格式序列化时转换成指定的格式。
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm")
private Date date;
@Test
public void testJsonFormat() throws IOException {
StudentWithAnnotations student = buildStudentWithAnnotations();
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
System.out.println(json);
}
输出
{
"age" : 18,
"date" : "2020-10-21 17:33",
"height" : 100,
"teacher" : {
"name" : "张老师"
},
"firstName" : "Jackson"
}
4.4 注解总结
注解 | 用法 |
---|---|
@JsonProperty | 用于属性,把属性的名称序列化时转换为另外一个名称。示例:@JsonProperty(“birth_date”) private Date birthDate |
@JsonIgnore | 可用于字段、getter/setter、构造函数参数上,作用相同,都会对相应的字段产生影响。使相应字段不参与序列化和反序列化。 |
@JsonIgnoreProperties | 该注解是类注解。该注解在Java类和JSON不完全匹配的时候使用。 |
@JsonFormat | 用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例:@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) public Date getBirthDate() |
@JsonPropertyOrder | 用于类, 和 @JsonProperty 的index属性类似,指定属性在序列化时 json 中的顺序 , 示例:@JsonPropertyOrder({ “birth_Date”, “name” }) public class Person |
@JsonCreator | 用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。示例:@JsonCreator public Person(@JsonProperty(“name”)String name) {…} |
@JsonAnySetter | 用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); } |
@JsonAnyGetter | 用于方法 ,获取所有未序列化的属性 public Map<String, Object> any() { return map; } |
@JsonNaming | 类注解。序列化的时候该注解可将驼峰命名的字段名转换为下划线分隔的小写字母命名方式。反序列化的时候可以将下划线分隔的小写字母转换为驼峰命名的字段名。示例:@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) |
@JsonRootName | 类注解。需开启mapper.enable(SerializationFeature.WRAP_ROOT_VALUE),用于序列化时输出带有根属性名称的 JSON 串,形式如 {“root_name”:{“id”:1,“name”:“zhangsan”}}。但不支持该 JSON 串反序列化。 |
5 日期处理
不同类型的日期类型,JackSon 的处理方式也不同。
5.1 普通日期
对于日期类型为java.util.Calendar
, java.util.GregorianCalendar
,java.sql.Date
, java.util.Date
, java.sql.Timestamp
,若不指定格式,在 json 文件中将序列化为 long 类型的数据。显然这种默认格式,可读性差,转换格式是必要的。
JackSon 有很多方式转换日期格式。
-
注解方式,使用 @JsonFormat 注解指定日期格式。
-
ObjectMapper 方式,调用 ObjectMapper 的方法 setDateFormat,将序列化为指定格式的 string 类型的数据。
上面已经介绍过啦
5.2 java8的日期
对于日期类型为java.time.LocalDate
, java.time.LocalDateTime
,还需要添加代码 ,同时添加相应的依赖 jar 包。
ObjectMapper mapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
演示
给Teacher增加两个属性
@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private String name;
private LocalDate localDate;
private LocalDateTime localDateTime;
}
@Test
public void test01() throws JsonProcessingException {
Teacher teacher = new Teacher();
teacher.setName("张老师");
teacher.setLocalDate(LocalDate.now());
teacher.setLocalDateTime(LocalDateTime.now());
objectMapper.registerModule(new JavaTimeModule());
String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(teacher);
System.out.println(value);
}
输出:
{
"name" : "张老师",
"localDate" : [ 2020, 10, 21 ],
"localDateTime" : [ 2020, 10, 21, 17, 55, 53, 375000000 ]
}
这个时间格式不太友好,可以直接使用我们的注解去进行格式化
@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private String name;
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
private LocalDate localDate;
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;
}
再次运行结果
{
"name" : "张老师",
"localDate" : "2020-10-21",
"localDateTime" : "2020-10-21 17:58:22"
}
5.3 Joda日期
对于日期类型为 org.joda.time.DateTime,还需要添加代码 mapper.registerModule(new JodaModule())
,同时添加相应的依赖 jar 包
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.9.10</version>
</dependency>
6 对象集合
Jackson 对泛型反序列化也提供很好的支持。
6.1 List
对于 List 类型 ,可以调用 constructCollectionType 方法来序列化,也可以构造 TypeReference 来序列化。
演示
@Test
public void test() throws IOException {
ObjectMapper mapper = new ObjectMapper();
// 造数据
List<Student> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Student student = new Student();
student.setName("Tom");
student.setAge(new Random().nextInt(100));
student.setDate(new Date());
list.add(student);
}
System.out.println("序列化");
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
System.out.println(jsonInString);
System.out.println("反序列化:使用 javaType");
CollectionType javaType = mapper.getTypeFactory().constructCollectionType(List.class, Student.class);
List<Student> personList = mapper.readValue(jsonInString, javaType);
System.out.println(personList);
System.out.println("反序列化:使用 TypeReference");
List<Student> personList2 = mapper.readValue(jsonInString, new TypeReference<List<Student>>() {
});
System.out.println(personList2);
}
序列化
[ {
"name" : "Tom",
"age" : 40,
"date" : 1603285233310,
"height" : 0,
"course" : null,
"teacher" : null
}, {
"name" : "Tom",
"age" : 51,
"date" : 1603285233310,
"height" : 0,
"course" : null,
"teacher" : null
}, {
"name" : "Tom",
"age" : 87,
"date" : 1603285233310,
"height" : 0,
"course" : null,
"teacher" : null
} ]
反序列化:使用 javaType
[Student(name=Tom, age=40, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=51, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=87, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null)]
反序列化:使用 TypeReference
[Student(name=Tom, age=40, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=51, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=87, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null)]
6.2 Map
对于 map 类型, 与 List 的实现方式相似。
public void test6() throws IOException {
ObjectMapper mapper = new ObjectMapper();
//第二参数是 map 的 key 的类型,第三参数是 map 的 value 的类型
MapType javaType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Student.class);
// 造数据
Map<String, Student> map = new HashMap<>();
for (int i = 0; i < 3; i++) {
Student student = new Student();
student.setName("Tom");
student.setAge(new Random().nextInt(100));
student.setDate(new Date());
map.put("key" + i, student);
}
System.out.println("序列化");
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
System.out.println(jsonInString);
System.out.println("反序列化: 使用 javaType");
Map<String, Student> personMap = mapper.readValue(jsonInString, javaType);
System.out.println(personMap);
System.out.println("反序列化: 使用 TypeReference");
Map<String, Student> personMap2 = mapper.readValue(jsonInString, new TypeReference<Map<String, Student>>() {
});
System.out.println(personMap2);
}
序列化
{
"key1" : {
"name" : "Tom",
"age" : 44,
"date" : 1603285404538,
"height" : 0,
"course" : null,
"teacher" : null
},
"key2" : {
"name" : "Tom",
"age" : 44,
"date" : 1603285404538,
"height" : 0,
"course" : null,
"teacher" : null
},
"key0" : {
"name" : "Tom",
"age" : 2,
"date" : 1603285404538,
"height" : 0,
"course" : null,
"teacher" : null
}
}
反序列化: 使用 javaType
{key1=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key2=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key0=Student(name=Tom, age=2, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null)}
反序列化: 使用 TypeReference
{key1=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key2=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key0=Student(name=Tom, age=2, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null)}
7 属性可视化
JackSon 默认不是所有的属性都可以被序列化和反序列化。默认的属性可视化的规则如下:
-
若该属性修饰符是 public,该属性可序列化和反序列化。
-
若属性的修饰符不是 public,但是它的 getter 方法和 setter 方法是 public,该属性可序列化和反序列化。因为 getter 方法用于序列化, 而 setter 方法用于反序列化。
-
若属性只有 public 的 setter 方法,而无 public 的 getter 方 法,该属性只能用于反序列化。