SpringBoot-JackSon

欢迎你来读这篇博客,这篇博客主要是关于SpringBoot-JackSon 使用指南
其中包括了关于我的见解和收集的知识分享。

序言

  • 环境
  • JDK 17
  • IDEA
  • Maven 3
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

<mvn>
<!-- POM模块引入 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- 项目模块引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 在Spring Boot项目中,通常不需要手动导入Jackson的依赖,因为spring-boot-starter-web已经包含了这些依赖。但如果你需要单独引入,可以在pom.xml文件中添加以下依赖 -->
<!-- Jackson核心库 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>lasted-version</version>
</dependency>
</mvn>

正文

Jackson 是一个广泛使用的开源类库,用于处理 JSON 和 XML 数据的格式化。它在日常开发中非常流行,尤其是在 Spring MVC 框架中,默认的
JSON 解析器就是 Jackson。

除了 Jackson,还有一些常见的 JSON 解析器,比如 Jsonlib、Gson 和 fastjson 等。然而,Jackson 在处理大型 JSON
文件时,凭借其较快的处理速度、较低的内存占用以及出色的性能,显现出了明显的优势。它还提供了灵活的 API,便于扩展和定制。

总之,Jackson 是一款非常强大的处理 JSON 和 XML 格式的开源类库,非常适合开发中使用。它在 Spring Boot 项目中也是默认的 JSON
处理库,主要用于对象与 JSON 之间的序列化和反序列化。接下来,将详细介绍在 Spring Boot 中如何使用
Jackson,包括基本配置、注解使用、自定义序列化器与反序列化器以及如何处理复杂数据类型等内容。

Jackson 核心模块

  • jackson-core:核心包,它提供基于”流模式”解析的相关 API,它包括JsonPaser和JsonGenerator。Jackson 内部实现正是通过高性能的流模式
    API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

  • jackson-annotations:注解包,提供标准注解功能。

  • jackson-databind:数据绑定包, 提供基于”对象绑定” 解析的相关 API ( ObjectMapper ) 和”树模型” 解析的相关 API
    (JsonNode);基于”对象绑定” 解析的 API 和”树模型”解析的 API 依赖基于”流模式”解析的 API

性能分析

Jackson、Gson、Fastjson 是三个最常用的 JSON 库。它们各有优缺点,性能和使用场景也有所不同。下面我们从性能、功能、易用性和安全性等方面进行详细对比。

库名称 序列化性能 反序列化性能 内存占用 描述
Jackson 性能最优,适合高并发场景。支持流式 API(JsonParser 和 JsonGenerator),适合处理大文件。多格式支持如 JSON/XML/YAML/CSV。 学习曲线陡峭(配置复杂)。
Fastjson 极高 极低 性能较好,但存在安全隐患,新版本可用。但 历史上多次曝出反序列化漏洞。 Fastjson 1.x:已停止维护,存在反序列化RCE等严重漏洞。Fastjson2:重构版本,修复安全问题并提升性能(性能较1.x提升20%+)
Gson 性能中等,适合简单场景,适合新手,学习难度平缓,API简洁。
  • Jackson的流式API 在处理GB级JSON时内存占用仅为Gson的1/3;
  • Gson的宽松映射 允许字段名不匹配、无参构造器缺失,容错性最佳。
  • Fastjson2的Path查询 支持类XPath语法,可直接提取嵌套字段(如JSONPath.eval(json, “$.user.address”));
  • 序列化场景:Fastjson2 > Jackson > Gson
  • 反序列化场景:Fastjson2 ≈ Jackson > Gson

配置

通过yaml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
jackson:
# 设置日期格式
date-format: yyyy-MM-dd HH:mm:ss
# 设置时区
time-zone: Asia/Shanghai
# 设置默认属性包含方式,例如非空
default-property-inclusion: non_null
serialization:
# 设置序列化时是否格式化输出
indent-output: true
deserialization:
# 设置反序列化时是否忽略未知属性
fail-on-unknown-properties: false
parser:
# 设置解析器是否允许未转义的控制字符
allow-unquoted-control-chars: true
# 设置解析器是否允许单引号
allow-single-quotes: true

自定义配置

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
37
38
39
40
41
42
43
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

@Configuration
public class JacksonConfig {

@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();

// 设置日期格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

// 设置时区
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));

// 设置序列化时是否格式化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

// 设置反序列化时是否忽略未知属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

// 设置解析器是否允许未转义的控制字符
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

// 设置解析器是否允许单引号
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

// 添加Java 8时间模块支持
objectMapper.registerModule(new JavaTimeModule());

return objectMapper;
}
}

注解

  • @JsonIgnore:忽略字段的序列化和反序列化。
  • @JsonProperty:指定字段的JSON键名。
  • @JsonCreator:此注解用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。
  • @JsonFormat:指定日期格式。
  • @JsonInclude:控制字段的序列化条件。
  • @JsonView:控制视图。
  • @JsonAlias:为反序列化期间要接受的属性定义一个或多个替代名称。
  • @JsonPropertyOrder:指定字段的序列化顺序。
  • @JsonRawValue:将字段值作为原始JSON字符串处理。
  • @JsonAnyGetter和@JsonAnySetter:处理动态属性。
  • @JsonValue 自动适配枚举
  • @JsonIdentityInfo注解来避免无限递归
  • @JsonTypeInfo和@JsonSubTypes注解来处理多态类型

示例

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@JsonInclude(JsonInclude.Include.NON_NULL) // 忽略值为null的属性
@JsonPropertyOrder({"name", "age", "email"}) // 控制属性的序列化顺序
public class User {

@JsonProperty("user_name") // 设置属性的JSON名称
private String name;

private int age;

@JsonIgnore // 忽略此属性的序列化和反序列化
private String password;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") // 设置日期格式和时区
private Date createdDate;

@JsonProperty("user_email") // 设置属性的JSON名称
private String email;

@JsonInclude(JsonInclude.Include.NON_NULL) // 控制字段的序列化条件
private String email;

@JsonRawValue // 将字段值作为原始JSON字符串处理
private String rawJson;

private CategoryEnum category;

private Map<String, Object> additionalProperties;

@JsonAnyGetter
public Map<String, Object> any() {
return additionalProperties;
}

@JsonAnySetter
public void set(String name, Object value) {
if (additionalProperties == null) {
additionalProperties = new HashMap<>();
}
additionalProperties.put(name, value);
}

// 其他构造函数、getter和setter省略
}

public enum CategoryEnum {

WEB("Web", 1),
APP("App", 2),
EMAIL("Email", 3);

private final String category;

@JsonValue // json序列化反序列化的时候自动处理 会自动返回 这个值,接受这个值 自动映射为 枚举
private final Integer value;

CategoryEnum(String category, Integer value) {
this.category = category;
this.value = value;
}
}

序列化与反序列化

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

// 可以通过注入 或者自己 new一个
@Autowired
private ObjectMapper objectMapper;

// 序列化
String jsonString = objectMapper.writeValueAsString(user);

// 反序列化
User user = objectMapper.readValue(jsonString, User.class);

// 序列化Java对象列表为JSON字符串
String jsonString = objectMapper.writeValueAsString(users);

// 反序列化JSON字符串为Java对象列表
List<User> users = objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));

// 序列化Map为JSON字符串
String jsonString = objectMapper.writeValueAsString(map);

// 反序列化JSON字符串为Map
Map<String, Object> resultMap = objectMapper.readValue(jsonString, Map.class);

// 循环引用
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class User {
private Long id;
private String name;
private User friend;
}

// 多态问题
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
interface Animal {}

@Data
class Dog implements Animal {
private String breed;
}

@Data
class Cat implements Animal {
private String color;
}

public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();

// 创建多态对象
Animal dog = new Dog("German Shepherd");
Animal cat = new Cat("Black");

// 序列化多态对象为JSON字符串
String jsonStringDog = mapper.writeValueAsString(dog);
String jsonStringCat = mapper.writeValueAsString(cat);
System.out.println("序列化后的JSON字符串 (Dog): " + jsonStringDog);
System.out.println("序列化后的JSON字符串 (Cat): " + jsonStringCat);

// 反序列化JSON字符串为多态对象
Animal deserializedDog = mapper.readValue(jsonStringDog, Animal.class);
Animal deserializedCat = mapper.readValue(jsonStringCat, Animal.class);
System.out.println("反序列化后的多态对象 (Dog): " + deserializedDog);
System.out.println("反序列化后的多态对象 (Cat): " + deserializedCat);
}
}

自定义序列化器

1
2
3
4
5
6
7
8
9
public class CustomDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}

自定义反序列化器

1
2
3
4
5
6
7
8
9
10
11
12
public class CustomDateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
return dateFormat.parse(p.getValueAsString());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}

使用自定义序列化和反序列化器

1
2
3
4
5
6
7
public class User {
private String name;

@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date registerDate;
}

参考资料

启示录

富贵岂由人,时会高志须酬。

能成功于千载者,必以近察远。


SpringBoot-JackSon
https://allendericdalexander.github.io/2025/08/04/Jackson/
作者
AtLuoFu
发布于
2025年8月4日
许可协议