Fastjson2 快速上手使用指南
作为 Java 开发者,JSON 处理几乎是日常工作中最基础也是最频繁的操作之一。现在介绍 Fastjson2库的使用,它是阿里开源的下一代高性能 JSON 库,它相比老版 Fastjson 在性能和安全性上都有了显著提升。
为什么选择 Fastjson2?
- 性能卓越:在序列化和反序列化速度上,Fastjson2 相比其他 JSON 库(如 Jackson、Gson)有 2-3 倍的提升
- 安全性增强:修复了 Fastjson1 中的 AutoType 相关漏洞,默认关闭了自动类型绑定
- API 友好:支持链式调用、Lambda 表达式、Kotlin 等现代语法
- 功能丰富:支持 JSONPath、JSON Schema、国际化等高级特性
- 零依赖:核心包无任何第三方依赖,体积小(约 <1MB)
安全性机制详解
Fastjson2 从架构层面彻底移除了 Fastjson 1.x 中导致 AutoType 漏洞的机制,从根本上解决了远程代码执行等安全风险。Fastjson2 默认关闭了自动类型绑定,并引入了白名单机制、类加载隔离和反序列化沙箱等安全策略,使得企业可以放心使用。在实际使用中,建议始终保持默认的 SafeMode 安全模式,除非明确需要 AutoType 功能且经过充分的安全评估。
环境准备Maven
在 Maven 项目的 pom.xml 中添加依赖:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.61</version>
</dependency>
如果使用 Gradle:
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2:2.0.61'
}
Fastjson v1 兼容模块
如果原来使用 Fastjson 1.2.x 版本,可以引入兼容包以降低升级成本。注意:兼容包不能保证 100% 兼容,请务必充分测试验证。
Maven 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.61</version>
</dependency>
Gradle 依赖
dependencies {
implementation 'com.alibaba:fastjson:2.0.61'
}
Fastjson Kotlin 集成模块
如果项目使用 Kotlin 开发,推荐引入 fastjson2-kotlin 模块,该模块针对 Kotlin 特性进行了优化(如支持数据类、空安全等)。
Maven 依赖
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-kotlin</artifactId>
<version>2.0.61</version>
</dependency>
Gradle 依赖
dependencies {
implementation("com.alibaba.fastjson2:fastjson2-kotlin:2.0.61")
}
Fastjson Extension 扩展模块
如果项目集成了 Spring Framework、Spring Boot 等框架,可以引入 fastjson2-extension 模块,提供与框架的无缝集成支持。
Maven 依赖
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.61</version>
</dependency>
Gradle 依赖
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2-extension:2.0.61'
}
基础用法:序列化与反序列化
Fastjson2 的核心操作只有两个:将 Java 对象转为 JSON 字符串(序列化),以及将 JSON 字符串转回 Java 对象(反序列化)。
1. 序列化(对象 → JSON)
import com.alibaba.fastjson2.JSON;
import java.time.LocalDate;
// 定义一个简单的实体类
public class User {
private String name;
private int age;
private LocalDate birthday;
// 构造器、getter/setter 省略(可使用 Lombok @Data)
}
// 序列化
User user = new User();
user.setName("张三");
user.setAge(30);
user.setBirthday(LocalDate.of(1996, 5, 15));
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);
// 输出:{"age":30,"birthday":"1996-05-15","name":"张三"}
2. 反序列化(JSON → 对象)
String json = "{\"name\":\"李四\",\"age\":32,\"birthday\":\"1994-08-20\"}";
User user = JSON.parseObject(json, User.class);
System.out.println(user.getName()); // 输出:李四
System.out.println(user.getAge()); // 输出:32
3. 处理集合与泛型
// 解析 JSON 数组
String arrayJson = "[{\"name\":\"王五\",\"age\":25},{\"name\":\"赵六\",\"age\":32}]";
List<User> userList = JSON.parseArray(arrayJson, User.class);
System.out.println(userList.size()); // 输出:2
// 使用 TypeReference 处理复杂泛型
String mapJson = "{\"key1\":[1,2,3],\"key2\":[4,5,6]}";
Map<String, List<Integer>> map = JSON.parseObject(
mapJson,
new TypeReference<Map<String, List<Integer>>>(){}
);
System.out.println(map.get("key1")); // 输出:[1, 2, 3]
处理泛型中的泛型例子:
// 定义一个泛型响应类
public class Result<T> {
public int code;
public T data;
}
// 反序列化时指定 T 的具体类型
String json = "{\"code\":200,\"data\":{\"name\":\"王五\",\"age\":30}}";
Result<User> result = JSON.parseObject(json, new TypeReference<Result<User>>(){});
4. JSONObject / JSONArray 解析
在许多场景下,我们并不需要定义完整的 Java 实体类,而只需要临时解析 JSON 数据。Fastjson2 提供了 JSONObject 和 JSONArray 来完成这类手动解析任务。
// 定义User类
@Data
public class User {
private int age;
private String name;
public User(int age, String name) {
this.age = age;
this.name = name;
}
}
// 解析 JSON 字符串为 JSONObject
String text = "{\"id\": 2, \"name\": \"fastjson2\"}";
JSONObject obj = JSON.parseObject(text);
int id = obj.getIntValue("id"); // 2
String name = obj.getString("name"); // "fastjson2"
// 解析 JSON 字符串为 JSONArray
String arrayText = "[2, \"fastjson2\"]";
JSONArray array = JSON.parseArray(arrayText);
int id2 = array.getIntValue(0); // 2
String name2 = array.getString(1); // "fastjson2"
// 从 JSONObject / JSONArray 中提取 Java 对象
User userFromObj = obj.getObject("key", User.class);
int idValue = array.getIntValue(0);
String nameValue = array.getString(1);
User userFromArray = new User(idValue, nameValue);
// JSONObject / JSONArray 转为 Java 对象
User user = obj.toJavaObject(User.class);
List<User> users = new ArrayList<>();
int idValue1 = array.getIntValue(0);
String nameValue1 = array.getString(1);
users.add(new User(idValue1, nameValue1));
JSONPath 支持
Fastjson2 将 JSONPath 内建为原生操作,无需独立解析器或额外转换,可直接在 JSON 对象上执行路径查询与数据提取。JSONPath 是一种用于在 JSON 文档中定位和提取数据的查询语言,类似于 XPath 在 XML 中的作用。通过 JSONPath,可以直接从 JSON 中提取部分数据,无需完整解析整个文档。
String text = "{\"id\": 100, \"name\": \"Alice\", \"scores\": [85, 92, 78]}";
// 创建 JSONPath(可缓存复用,以提升性能)
JSONPath path = JSONPath.of("$.id");
// 从 JSON 字符串中提取数据
JSONReader parser = JSONReader.of(text);
Object result = path.extract(parser); // 结果为 100
// 对于二进制 JSONB 格式的数据,同样支持 JSONPath 查询
byte[] bytes = ...;
JSONPath path2 = JSONPath.of("$.id");
JSONReader reader = JSONReader.ofJSONB(bytes);
Object result2 = path2.extract(reader);
JSONB 二进制格式
Fastjson2 除了支持标准的文本 JSON 格式外,还提供了 JSONB(Fastjson2 Binary)二进制序列化格式。JSONB 相比文本 JSON 在序列化体积和解析速度上都有显著优势,特别适合在高性能场景下使用。
JSONB的详细说明,请看这里。
// 将 Java 对象序列化为 JSONB 字节数组
User user = new User();
user.setName("张三");
user.setAge(28);
byte[] bytes = JSONB.toBytes(user);
// 也可以使用特性进行优化
byte[] bytesOptimized = JSONB.toBytes(user, JSONWriter.Feature.BeanToArray);
// 将 JSONB 数据反序列化为 Java 对象
byte[] bytesFrom = ...; // JSONB 格式的字节数组
User user2 = JSONB.parseObject(bytesFrom, User.class);
// 支持数组映射特性
User userOptimized = JSONB.parseObject(bytesFrom, User.class, JSONReader.Feature.SupportArrayToBean);
常用配置与特性
字段命名策略
// 使用下划线分隔命名(例如 user_name → userName)
String json = JSON.toJSONString(user, JSONWriter.Feature.FieldBased);
日期格式化
// 全局日期格式化
JSON.config("yyyy-MM-dd'T'HH:mm:ssXXX", TimeZone.getTimeZone("Asia/Shanghai"));
// 或者使用注解自定义格式
public class User {
@JSONField(format = "yyyy/MM/dd")
private LocalDate birthday;
}
忽略空值
String json = JSON.toJSONString(user, JSONWriter.Feature.WriteMapNullValue);
@JSONField 注解详解
@JSONField 注解是 Fastjson2 中最常用的配置注解,支持以下常用属性:
| 属性 | 作用 | 示例 |
|---|---|---|
name | 指定 JSON 字段与 Java 字段的映射名称 | @JSONField(name = "user_name") |
format | 指定日期格式 | @JSONField(format = "yyyy-MM-dd HH:mm:ss") |
serialize | 是否序列化该字段 | @JSONField(serialize = false) |
deserialize | 是否反序列化该字段 | @JSONField(deserialize = false) |
alternateNames | 指定备用名称,支持多个别名 | @JSONField(alternateNames = {"uid", "userId"}) |
public class User {
@JSONField(name = "user_name")
private String name;
@JSONField(format = "yyyy-MM-dd")
private LocalDate birthday;
@JSONField(serialize = false)
private String password;
}
实际案例:Web API 交互
以下是一个完整的实际应用场景,模拟从 REST API 获取用户数据并解析:
// 模拟 API 返回的 JSON
String apiResponse = """
{
"code": 200,
"message": "success",
"data": [
{"id": 1, "name": "Alice", "scores": [85, 92, 78]},
{"id": 2, "name": "Bob", "scores": [90, 88, 95]}
]
}
""";
// 定义嵌套结构
record ApiResult<T>(int code, String message, T data) {}
record Student(int id, String name, List<Integer> scores) {}
// 解析
ApiResult<List<Student>> result = JSON.parseObject(
apiResponse,
new TypeReference<ApiResult<List<Student>>>(){}
);
// 使用数据
result.data().forEach(student -> {
double avg = student.scores().stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0);
System.out.printf("%s 的平均分是 %.1f%n", student.name(), avg);
});
// 输出:
// Alice 的平均分是 85.0
// Bob 的平均分是 91.0
性能对比速览(非严谨测试)
| 操作 | Fastjson2 | Jackson | Gson |
|---|---|---|---|
| 序列化 10万次 | 120ms | 310ms | 450ms |
| 反序列化 10万次 | 150ms | 380ms | 520ms |
性能优化最佳实践
- 处理超大对象:当序列化的 JSON 超过 10MB 时,建议启用
LargeObject特性,该特性采用流式处理替代全缓冲模式,可显著降低内存使用量:
String result = JSON.toJSONString(dataClass, JSONWriter.Feature.LargeObject); - API 设计建议:建议不要在代码中直接使用 Fastjson2 的 API,而是封装一个统一的 JSON 工具类。这样可以降低对特定 JSON 库的依赖,方便未来库的升级或替换。
- 泛型处理注意事项:处理泛型时必须使用
TypeReference,否则会导致类型信息丢失:
正确:Map<String, List<Integer>> map = JSON.parseObject(json, new TypeReference<Map<String, List<Integer>>>() {});
错误:Map<String, List<Integer>> map = JSON.parseObject(json, Map.class);
从 Fastjson 1.x 迁移指南
从 Fastjson 1.x 升级到 Fastjson 2.x 时,需要注意以下要点:
- 包名变更:从
com.alibaba.fastjson变更为com.alibaba.fastjson2,直接替换包名即可。 - 注解行为变更:Fastjson 2.x 更加遵循 JSON 规范,
@JSONField的 name 属性现在要求字段名称完全匹配(除非显式配置别名)。 - 引入兼容模块:如果原来使用 Fastjson 1.2.x 版本,可以使用兼容包
com.alibaba:fastjson:2.0.61,但不能保证 100% 兼容,请仔细测试验证。
总结与最佳实践
- 优先使用 Fastjson2:新项目推荐直接使用 Fastjson2,老项目可以逐步迁移
- 避免使用 AutoType:除非必要,否则保持默认的
SafeMode(安全模式) - 善用 TypeReference:处理泛型时一定要使用
TypeReference - 注意性能敏感场景:配合
@JSONField注解和JSONWriter.Feature可以进一步优化
Fastjson2 的学习曲线非常平缓,从今天开始,不妨在你的项目中将老版 Fastjson 或 Jackson 替换为 Fastjson2,体验一下“快”的快乐!

