抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文介绍了如何在Java中使用GSON进行JSON的序列化和反序列化操作。

环境

Windows 10 企业版 LTSC 21H2
Java 1.8

1 简介

Jackson是一个高性能的JSON处理库,用于将Java对象与JSON数据格式进行相互转换。它提供了灵活的API,方便开发者在Java应用程序中处理JSON数据。

2 基础使用

核心组件:

  • jackson-core:提供底层的API接口。
  • jackson-annotations:提供丰富的注解。
  • jackson-databind:提供数据绑定功能,包含上面两个组件。

pom.xml中添加依赖:

pom.xml
1
2
3
4
5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.1</version>
</dependency>

导入jackson-databind后,会自动导入jackson-core和jackson-annotations到项目中。

定义Java类:

Student.java
1
2
3
4
5
6
public class Student {
private String name;
private int age;
private List<String> hobbies;
// 省略其他方法
}

序列化:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
// 创建Student对象
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHobbies(Arrays.asList("阅读", "编程", "运动"));
// 创建ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();
// 将对象序列化为JSON字符串
try {
String json = objectMapper.writeValueAsString(student);
System.out.println("序列化结果: " + json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}

反序列化:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
// 创建JSON字符串
String json = "{\"name\":\"张三\",\"age\":20,\"hobbies\":[\"阅读\",\"编程\",\"运动\"]}";
// 创建ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();
// 将JSON字符串反序列化为Student对象
try {
Student student = objectMapper.readValue(json, Student.class);
System.out.println("反序列化结果: " + student.getName() + ", " + student.getAge() + ", " + student.getHobbies());
} catch (IOException e) {
e.printStackTrace();
}
}

3 处理泛型

使用TypeReference处理泛型:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) throws IOException {
Student student = new Student();
student.setName("张三");
List<Student> studentList = new ArrayList<>();
studentList.add(student);
ObjectMapper objectMapper = new ObjectMapper();
// [{"name":"张三"}]
String jsonString = objectMapper.writeValueAsString(studentList);
System.out.println(jsonString);
// 张三
List<Student> jsonList = objectMapper.readValue(jsonString, new TypeReference<List<Student>>(){});
System.out.println(jsonList.get(0).getName());
}

4 流式处理

4.1 序列化

使用JsonGenerator类实现序列化。

常用方法:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 开始解析对象,并设置属性名
public void writeObjectFieldStart(String fieldName) throws IOException;
// 开始解析对象
public abstract void writeStartObject() throws IOException;
// 结束解析对象
public abstract void writeEndObject() throws IOException;
// 开始解析数组,并设置属性名
public void writeArrayFieldStart(String fieldName) throws IOException;
// 开始解析数组
public abstract void writeStartArray() throws IOException;
// 结束解析数组
public abstract void writeEndArray() throws IOException;
// 设置属性名
public abstract void writeFieldName(String name) throws IOException;
// 设置布尔属性值
public abstract void writeBoolean(boolean state) throws IOException;
// 设置字符串属性值
public abstract void writeString(String text) throws IOException;
// 设置null属性值
public abstract void writeNull() throws IOException;
// 设置布尔属性值和属性名
public void writeBooleanField(String fieldName, boolean value) throws IOException;
// 设置int类型属性值和属性名
public void writeNumberField(String fieldName, int value) throws IOException;
// 设置long类型属性值和属性名
public void writeNumberField(String fieldName, long value) throws IOException;
// 设置float类型属性值和属性名
public void writeNumberField(String fieldName, float value) throws IOException;
// 设置double类型属性值和属性名
public void writeNumberField(String fieldName, double value) throws IOException;
// 设置字符串属性值和属性名
public void writeStringField(String fieldName, String value) throws IOException;
// 设置null属性值和属性名
public void writeNullField(String fieldName) throws IOException;
// 刷新缓冲区
public abstract void flush() throws IOException;

自动序列化:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHobbies(Arrays.asList("阅读", "编程", "运动"));
ObjectMapper objectMapper = new ObjectMapper();
try (StringWriter stringWriter = new StringWriter();
JsonGenerator jsonGenerator = objectMapper.getFactory().createGenerator(stringWriter)) {
objectMapper.writeValue(jsonGenerator, student);
System.out.println("序列化结果: " + stringWriter);
} catch (Exception e) {
e.printStackTrace();
}
}

手动序列化:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHobbies(Arrays.asList("阅读", "编程", "运动"));
ObjectMapper objectMapper = new ObjectMapper();
try (StringWriter stringWriter = new StringWriter();
JsonGenerator jsonGenerator = objectMapper.getFactory().createGenerator(stringWriter)) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", student.getName());
jsonGenerator.writeNumberField("age", student.getAge());
jsonGenerator.writeArrayFieldStart("hobbies");
for (String hobby : student.getHobbies()) {
jsonGenerator.writeString(hobby);
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
jsonGenerator.flush();
System.out.println("序列化结果: " + stringWriter);
} catch (Exception e) {
e.printStackTrace();
}
}

4.2 反序列化

使用JsonParser类实现反序列化。

常用方法:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 获取下一个元素的类型
public abstract JsonToken nextToken() throws IOException;
// 获取当前元素的名称
public abstract String getCurrentName() throws IOException;
// 获取当前元素的布尔类型的值
public boolean getBooleanValue() throws IOException;
// 获取当前元素的int类型的值
public abstract int getIntValue() throws IOException;
// 获取当前元素的long类型的值
public abstract long getLongValue() throws IOException;
// 获取当前元素的float类型的值
public abstract float getFloatValue() throws IOException;
// 获取当前元素的double类型的值
public abstract double getDoubleValue() throws IOException;
// 获取当前元素的字符串类型的值
public abstract String getText() throws IOException;
// 跳过当前元素
public abstract JsonParser skipChildren() throws IOException;

自动反序列化:

java
1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
String json = "{\"name\":\"张三\",\"age\":20,\"hobbies\":[\"阅读\",\"编程\",\"运动\"]}";
ObjectMapper objectMapper = new ObjectMapper();
try (StringReader stringReader = new StringReader(json);
JsonParser jsonParser = objectMapper.getFactory().createParser(stringReader)) {
Student student = objectMapper.readValue(jsonParser, Student.class);
System.out.println("反序列化结果: " + student.getName() + ", " + student.getAge() + ", " + student.getHobbies());
} catch (Exception e) {
e.printStackTrace();
}
}

手动反序列化:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void main(String[] args) {
String json = "{\"name\":\"张三\",\"age\":20,\"hobbies\":[\"阅读\",\"编程\",\"运动\"]}";
ObjectMapper objectMapper = new ObjectMapper();
try (StringReader stringReader = new StringReader(json);
JsonParser jsonParser = objectMapper.getFactory().createParser(stringReader)) {
Student student = new Student();
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jsonParser.getCurrentName();
jsonParser.nextToken();
switch (fieldName) {
case "name":
student.setName(jsonParser.getText());
break;
case "age":
student.setAge(jsonParser.getIntValue());
break;
case "hobbies":
List<String> hobbies = new ArrayList<>();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
hobbies.add(jsonParser.getText());
}
student.setHobbies(hobbies);
break;
default:
jsonParser.skipChildren();
break;
}
}
System.out.println("反序列化结果: " + student.getName() + ", " + student.getAge() + ", " + student.getHobbies());
} catch (Exception e) {
e.printStackTrace();
}
}

5 修改配置

修改ObjectMapper默认配置。

常用方法:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 设置序列化特性
public ObjectMapper configure(SerializationFeature f, boolean state);
// 设置反序列化特性
public ObjectMapper configure(DeserializationFeature f, boolean state);
// 设置序列化和反序列化处理逻辑
public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Include incl);
// 设置序列化和反序列化处理逻辑,支持分开设置
public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Value incl);
// 设置日期和时间格式
public ObjectMapper setDateFormat(DateFormat dateFormat);
// 设置日期时区
public ObjectMapper setTimeZone(TimeZone tz);
// 注册自定义模块
public ObjectMapper registerModule(Module module);

SerializationFeature常用取值:

  • SerializationFeature.INDENT_OUTPUT:序列化时格式化输出,默认禁用,启用后格式化输出。
  • SerializationFeature.WRITE_NULL_MAP_VALUES:序列化时保留值为null的键值对,默认启用,禁用后忽略值为null的键值对。
  • SerializationFeature.WRITE_EMPTY_JSON_ARRAYS:序列化时保留空数组,默认启用,禁用后忽略空数组。
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:序列化时将日期转为时间戳,默认启用,禁用后输出字符串。

DeserializationFeature常用取值:

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:反序列化时如果存在对象未定义字段则抛出异常,默认启用,禁用后忽略未定义字段。
  • DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT:反序列化时将空字符串转换为null,默认禁用,启用后将空字符串转换为null。

JsonInclude.Include常用取值:

  • ALWAYS:处理所有属性,默认值。
  • NON_NULL:排除属性值为null的属性。
  • NON_ABSENT:排除属性值为null的属性,排除在逻辑上不存在的属性。
  • NON_EMPTY:排除属性值为null的属性,排除在逻辑上不存在的属性,排除空字符串,排除空集合和空数组。
  • NON_DEFAULT:排除属性值为默认值的属性。

示例:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) throws IOException {
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHobbies(Arrays.asList("阅读", "编程", "运动"));
ObjectMapper objectMapper = new ObjectMapper();
// 序列化配置
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 反序列化配置
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// 通用处理逻辑
objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
// 日期格式全局配置
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
// 序列化结果
String jsonString = objectMapper.writeValueAsString(student);
System.out.println("序列化结果: " + jsonString);
// 反序列化结果
Student jsonObject = objectMapper.readValue(jsonString, Student.class);
System.out.println("反序列化结果: " + jsonObject.getName() + ", " + jsonObject.getAge() + ", " + jsonObject.getHobbies());
}

6 字段处理

6.1 指定键名

6.1.1 双向可用

使用@JsonProperty注解指定Java字段名对应的JSON键名。

指定JSON键名:

java
1
2
3
4
public class Student {
@JsonProperty("student_name")
private String name;
}

反序列化支持多个JSON键名,以最后的值为准:

java
1
2
3
4
5
public class Student {
@JsonProperty("student_name")
@JsonAlias({"student-name", "student.name"})
private String name;
}

6.1.2 单向可用

只在序列化或反序列化生效:

  • 使用@JsonGetter注解指定Java字段名对应的JSON键名,只在序列化生效。
  • 使用@JsonSetter注解指定Java字段名对应的JSON键名,只在反序列化生效。

指定JSON键名:

java
1
2
3
4
5
6
7
8
9
10
11
public class Student {
@JsonGetter("student_name")
public String getName() {
return name;
}

@JsonSetter("student_name")
public void setName(String name) {
this.name = name;
}
}

6.2 忽略字段

使用@JsonIgnore注解忽略Java字段,不参与序列化和反序列化。

忽略Java字段:

java
1
2
3
4
public class Student {
@JsonIgnore
private String name;
}

使用@JsonIgnoreProperties注解忽略Java字段,不参与序列化和反序列化。支持使用ignoreUnknown属性在反序列化时忽略未定义字段。

忽略Java字段:

java
1
2
3
4
5
6
@JsonIgnoreProperties(value = {"name"}, ignoreUnknown = true)
public class Student {
private String name;
private int age;
private List<String> hobbies;
}

7 自定义处理

7.1 序列化

通过SimpleModule模块继承StdSerializer类实现自定义序列化:

StudentSerializer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class StudentSerializer extends StdSerializer<Student> {
protected StudentSerializer() {
super(Student.class);
}

@Override
public void serialize(Student student, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", student.getName());
jsonGenerator.writeNumberField("age", student.getAge());
jsonGenerator.writeArrayFieldStart("hobbies");
for (String hobby : student.getHobbies()) {
jsonGenerator.writeString(hobby);
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
}
}

使用自定义序列化器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
// 创建Student对象
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHobbies(Arrays.asList("阅读", "编程", "运动"));
// 创建自定义序列化器并注册模块
StudentSerializer studentSerializer = new StudentSerializer();
SimpleModule module = new SimpleModule();
module.addSerializer(Student.class, studentSerializer);
// 创建ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
// 将对象序列化为JSON字符串
try {
String json = objectMapper.writeValueAsString(student);
System.out.println("序列化结果: " + json);
} catch (IOException e) {
e.printStackTrace();
}
}

7.2 反序列化

通过SimpleModule模块继承StudentDeserializer类实现自定义反序列化:

StudentDeserializer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class StudentDeserializer extends StdDeserializer<Student> {
protected StudentDeserializer() {
super(Student.class);
}

@Override
public Student deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
Student student = new Student();
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jsonParser.getCurrentName();
jsonParser.nextToken();
switch (fieldName) {
case "name":
student.setName(jsonParser.getText());
break;
case "age":
student.setAge(jsonParser.getIntValue());
break;
case "hobbies":
List<String> hobbies = new ArrayList<>();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
hobbies.add(jsonParser.getText());
}
student.setHobbies(hobbies);
break;
default:
jsonParser.skipChildren();
break;
}
}
return student;
}
}

使用自定义反序列化器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
// 创建JSON字符串
String json = "{\"name\":\"张三\",\"age\":20,\"hobbies\":[\"阅读\",\"编程\",\"运动\"]}";
// 创建自定义反序列化器并注册模块
StudentDeserializer studentDeserializer = new StudentDeserializer();
SimpleModule module = new SimpleModule();
module.addDeserializer(Student.class, studentDeserializer);
// 创建ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
// 将JSON字符串反序列化为Student对象
try {
Student student = objectMapper.readValue(json, Student.class);
System.out.println("反序列化结果: " + student.getName() + ", " + student.getAge() + ", " + student.getHobbies());
} catch (IOException e) {
e.printStackTrace();
}
}

评论