FastJson2(JSON处理库)
# FastJson2(JSON处理库)
前言
FastJson2 是阿里巴巴广受欢迎的 FASTJSON 项目的全新升级版本,其核心目标是提供极致性能的 JSON 处理能力。相较于经典的 FastJson 1.x 版本,FastJson2 不仅在性能上实现了飞跃性的提升,更在安全性方面进行了彻底的革新,例如完全移除了备受争议的 autoType
白名单机制,从根本上消除了相关的安全隐患。同时,FastJson2 依然保持了其一贯的易用性和丰富的功能集,使其成为 Java 开发中处理 JSON 数据,尤其是对性能有高要求场景下的理想选择。本篇文档将深入探讨 FastJson2 的核心用法、高级特性及最佳实践。
# 一、FastJson2 环境配置与基础依赖
要在你的 Java 项目中集成并使用 FastJson2,首要步骤是在项目的构建配置文件中添加相应的依赖。
Maven 项目依赖配置:
如果你使用 Maven 作为项目管理工具,请在 pom.xml
文件中添加以下依赖项:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<!-- 建议使用官方推荐的最新稳定版本 -->
<version>2.0.26</version>
</dependency>
2
3
4
5
6
说明:请将
<version>
标签中的版本号替换为你项目需要使用的具体版本。撰写本文时,2.0.26
是一个较新的稳定版本。建议查阅 FastJson2 官方仓库以获取最新的版本信息。
Gradle 项目依赖配置:
如果你使用 Gradle,请在 build.gradle
文件中添加:
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2:2.0.26' // 同样,请使用最新稳定版本
}
2
3
参考资源:
- FastJson 1.x 升级到 FastJson2 指南 (opens new window):官方提供的详细升级步骤和注意事项。
- FastJson2 GitHub 官方仓库 (opens new window):获取最新版本、源码、问题反馈和社区支持。
# 二、JSON 对象与数组的构建与创建
FastJson2 提供了 JSONObject
和 JSONArray
两个核心类,用于以编程方式构建和操作 JSON 数据结构。
# 1. JSON 对象(JSONObject)的创建与操作
JSONObject
代表一个无序的键值对集合,类似于 Java 中的 Map
。它常用于表示单个实体对象,如用户信息、配置项等。
代码示例:
import com.alibaba.fastjson2.JSONObject;
/**
* FastJson2 JSONObject 创建示例
* 演示如何创建 JSON 对象并向其中添加不同类型的数据。
*/
public class JsonObjectCreationExample {
public static void main(String[] args) {
// 方法一:创建一个空的 JSONObject 实例
JSONObject userInfo = new JSONObject();
// 使用 put 方法向 JSONObject 中添加键值对
userInfo.put("name", "张三"); // 添加字符串类型的值
userInfo.put("age", 28); // 添加整数类型的值
userInfo.put("isVIP", true); // 添加布尔类型的值
userInfo.put("balance", 1268.50); // 添加浮点数类型的值
userInfo.put("registrationDate", new java.util.Date()); // 添加日期类型的值 (会被序列化为时间戳或指定格式)
userInfo.put("notes", null); // 添加 null 值
// 创建一个嵌套的 JSONObject 来表示地址信息
JSONObject addressInfo = new JSONObject();
addressInfo.put("city", "北京");
addressInfo.put("district", "朝阳区");
addressInfo.put("street", "望京 SOHO");
addressInfo.put("postcode", "100102");
// 将嵌套的 addressInfo 对象作为值添加到 userInfo 对象中
userInfo.put("address", addressInfo);
// 使用 toString() 方法将 JSONObject 转换为 JSON 格式的字符串输出
System.out.println("通过 put 方法创建的 JSON 对象:");
System.out.println(userInfo.toString()); // 默认输出紧凑格式
// 方法二:使用链式调用的 fluentPut 方法创建 JSONObject (更简洁)
JSONObject productInfo = new JSONObject()
.fluentPut("id", "P10086") // 添加商品 ID
.fluentPut("name", "高级人体工学椅") // 添加商品名称
.fluentPut("price", 1299.00) // 添加价格
.fluentPut("inStock", true) // 添加库存状态
.fluentPut("tags", new String[]{"办公", "舒适", "健康"}); // 添加字符串数组
System.out.println("\n通过 fluentPut 链式创建的 JSON 对象:");
System.out.println(productInfo.toString());
}
}
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
输出结果:
通过 put 方法创建的 JSON 对象:
{"name":"张三","age":28,"isVIP":true,"balance":1268.5,"registrationDate":1692514800000,"notes":null,"address":{"city":"北京","district":"朝阳区","street":"望京 SOHO","postcode":"100102"}}
通过 fluentPut 链式创建的 JSON 对象:
{"id":"P10086","name":"高级人体工学椅","price":1299.0,"inStock":true,"tags":["办公","舒适","健康"]}
2
3
4
5
核心API说明:
put(String key, Object value)
:向JSONObject
中添加或更新一个键值对。key
是字段名 (字符串),value
可以是任意 Java 对象 (基本类型、字符串、日期、JSONObject
、JSONArray
、POJO 等)。fluentPut(String key, Object value)
:与put
功能相同,但返回JSONObject
实例本身,允许进行链式调用,使代码更流畅。toString()
:将JSONObject
序列化为紧凑格式(无缩进和换行)的 JSON 字符串。
# 2. JSON 数组(JSONArray)的创建与操作
JSONArray
代表一个有序的值列表,类似于 Java 中的 List
。它常用于表示集合数据,如用户列表、商品列表、标签数组等。
代码示例:
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
/**
* FastJson2 JSONArray 创建示例
* 演示如何创建 JSON 数组并添加不同类型的元素。
*/
public class JsonArrayCreationExample {
public static void main(String[] args) {
// 方法一:创建一个空的 JSONArray 实例
JSONArray studentArray = new JSONArray();
// 创建第一个学生信息的 JSONObject
JSONObject student1 = new JSONObject();
student1.put("name", "张三");
student1.put("age", 18);
student1.put("grade", "高三");
student1.put("score", 89.5);
// 创建第二个学生信息的 JSONObject
JSONObject student2 = new JSONObject();
student2.put("name", "李四");
student2.put("age", 19);
student2.put("grade", "高三");
student2.put("score", 92.0);
// 使用 add 方法将 JSONObject 添加到 JSONArray 中
studentArray.add(student1); // 添加第一个学生对象
studentArray.add(student2); // 添加第二个学生对象
// 直接向 JSONArray 中添加基本类型的值
JSONArray numbersArray = new JSONArray();
numbersArray.add(10); // 添加整数
numbersArray.add(20.5); // 添加浮点数
numbersArray.add("Thirty"); // 添加字符串
numbersArray.add(true); // 添加布尔值
numbersArray.add(null); // 添加 null 值
// 将创建的 JSONArray 作为值添加到 JSONObject 中
JSONObject classInfo = new JSONObject();
classInfo.put("className", "高三(1)班");
classInfo.put("students", studentArray); // 添加包含复杂对象的数组
classInfo.put("miscData", numbersArray); // 添加包含混合基本类型的数组
// 输出包含数组的最终 JSON 对象
System.out.println("包含 JSONArray 的 JSONObject:");
System.out.println(classInfo.toString());
// 单独输出学生数组 JSON
System.out.println("\n学生 JSONArray:");
System.out.println(studentArray.toString());
// 通过索引访问 JSONArray 中的元素 (索引从 0 开始)
if (studentArray.size() > 0) {
JSONObject firstStudent = studentArray.getJSONObject(0); // 获取第一个元素 (JSONObject)
System.out.println("\n访问数组第一个元素(学生)的姓名: " + firstStudent.getString("name"));
}
if (numbersArray.size() > 2) {
String thirdElement = numbersArray.getString(2); // 获取第三个元素 (String)
System.out.println("访问混合类型数组的第三个元素: " + thirdElement);
}
// 方法二:使用静态工厂方法快速创建 JSONArray
JSONArray quickArray = JSONArray.of("Apple", "Banana", "Orange");
System.out.println("\n使用 JSONArray.of 创建的数组:");
System.out.println(quickArray.toString());
}
}
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
输出结果:
包含 JSONArray 的 JSONObject:
{"className":"高三(1)班","students":[{"name":"张三","age":18,"grade":"高三","score":89.5},{"name":"李四","age":19,"grade":"高三","score":92.0}],"miscData":[10,20.5,"Thirty",true,null]}
学生 JSONArray:
[{"name":"张三","age":18,"grade":"高三","score":89.5},{"name":"李四","age":19,"grade":"高三","score":92.0}]
访问数组第一个元素(学生)的姓名: 张三
访问混合类型数组的第三个元素: Thirty
使用 JSONArray.of 创建的数组:
["Apple","Banana","Orange"]
2
3
4
5
6
7
8
9
10
11
核心API说明:
add(Object element)
:向JSONArray
的末尾添加一个元素。元素可以是任何 Java 对象(基本类型、字符串、JSONObject
、JSONArray
等)。getJSONObject(int index)
:获取指定索引位置的元素,并期望它是一个JSONObject
。如果不是,可能会抛出异常。getString(int index)
/getIntValue(int index)
/getBooleanValue(int index)
等:获取指定索引位置的基本类型值。size()
:返回JSONArray
中元素的数量。JSONArray.of(Object... elements)
:静态工厂方法,用于快速创建包含指定元素的JSONArray
。
# 三、JSON 数据的访问与解析技巧
从已有的 JSONObject
或 JSONArray
中提取所需数据是 JSON 处理的核心环节。FastJson2 提供了健壮且类型安全的 API 来完成这些操作。
# 1. JSON 对象属性的读取与类型转换
从 JSONObject
中读取属性值时,应尽量使用类型安全的 getXXX
方法,并考虑属性可能不存在或值为 null
的情况。
代码示例:
import com.alibaba.fastjson2.JSONObject;
import java.math.BigDecimal;
import java.util.Date;
/**
* FastJson2 JSONObject 属性读取与访问示例
* 演示如何从 JSONObject 中安全、准确地读取各种类型的数据。
*/
public class JsonObjectAccessExample {
public static void main(String[] args) {
// 创建一个包含多种数据类型的 JSON 字符串用于解析
String userInfoJson = "{"
+ "\"id\": 10001,"
+ "\"name\": \"王小明\","
+ "\"age\": 25,"
+ "\"salary\": 15000.50,"
+ "\"isActive\": true,"
+ "\"joinDate\": \"2022-08-15\"," // 日期字符串
+ "\"lastLoginTimestamp\": 1692514800000," // 时间戳 (毫秒)
+ "\"description\": null," // 显式的 null 值
// "title": "工程师", // title 属性缺失
+ "\"department\": {"
+ "\"name\": \"研发部\","
+ "\"location\": \"A座3层\""
+ "}"
+ "}";
// 将 JSON 字符串解析为 JSONObject
JSONObject userInfo = JSONObject.parseObject(userInfoJson);
System.out.println("原始 JSONObject 内容: " + userInfo);
// 1. 读取基本类型的属性 - 使用类型安全的 getXXXValue 方法
// 这些方法在类型不匹配时会尝试转换,或在无法转换时返回默认值 (如 0, 0.0, false)
int id = userInfo.getIntValue("id"); // 获取整数
String name = userInfo.getString("name"); // 获取字符串
int age = userInfo.getIntValue("age"); // 获取整数
double salary = userInfo.getDoubleValue("salary"); // 获取双精度浮点数
BigDecimal exactSalary = userInfo.getBigDecimal("salary"); // 获取精确的小数 BigDecimal
boolean isActive = userInfo.getBooleanValue("isActive"); // 获取布尔值
System.out.println("\n基本属性读取:");
System.out.println("- ID: " + id);
System.out.println("- 姓名: " + name);
System.out.println("- 年龄: " + age);
System.out.println("- 薪资 (double): " + salary);
System.out.println("- 薪资 (BigDecimal): " + exactSalary);
System.out.println("- 是否活跃: " + isActive);
// 2. 读取日期/时间类型的属性
// FastJson2 会尝试自动识别多种日期格式和时间戳
Date joinDate = userInfo.getDate("joinDate"); // 尝试解析日期字符串
Date lastLogin = userInfo.getDate("lastLoginTimestamp"); // 尝试解析时间戳
System.out.println("\n日期/时间属性读取:");
System.out.println("- 入职日期: " + (joinDate != null ? new java.text.SimpleDateFormat("yyyy-MM-dd").format(joinDate) : "未提供"));
System.out.println("- 最后登录时间: " + lastLogin);
// 3. 安全地读取可能不存在或为 null 的属性
// getXXX(key, defaultValue) 方法在属性不存在或值为 null 时返回指定的默认值
String title = userInfo.getString("title", "普通员工"); // "title" 属性不存在,返回默认值
String description = userInfo.getString("description", "无描述"); // "description" 值为 null,返回默认值
System.out.println("\n带默认值的属性读取:");
System.out.println("- 职位: " + title);
System.out.println("- 描述: " + description);
// 4. 读取嵌套的 JSONObject 属性
JSONObject deptInfo = userInfo.getJSONObject("department"); // 获取嵌套的对象
if (deptInfo != null) { // 推荐在使用前检查是否为 null
String deptName = deptInfo.getString("name");
String location = deptInfo.getString("location");
System.out.println("\n嵌套对象属性读取:");
System.out.println("- 部门名称: " + deptName);
System.out.println("- 部门位置: " + location);
} else {
System.out.println("\n部门信息未提供。");
}
// 5. 检查属性是否存在 - 使用 containsKey 方法
boolean hasEmail = userInfo.containsKey("email");
boolean hasDepartment = userInfo.containsKey("department");
System.out.println("\n属性存在性检查:");
System.out.println("- 是否包含 'email' 属性: " + hasEmail);
System.out.println("- 是否包含 'department' 属性: " + hasDepartment);
// 6. 获取属性值,不进行类型转换 - 使用 get 方法 (返回 Object)
Object rawAge = userInfo.get("age");
Object rawDepartment = userInfo.get("department");
System.out.println("\n使用 get 获取原始值:");
System.out.println("- 年龄 (原始类型): " + (rawAge != null ? rawAge.getClass().getSimpleName() : "null"));
System.out.println("- 部门 (原始类型): " + (rawDepartment != null ? rawDepartment.getClass().getSimpleName() : "null"));
// 注意:获取后通常需要手动进行类型检查和转换
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
输出结果:
原始 JSONObject 内容: {"id":10001,"name":"王小明","age":25,"salary":15000.50,"isActive":true,"joinDate":"2022-08-15","lastLoginTimestamp":1692514800000,"description":null,"department":{"name":"研发部","location":"A座3层"}}
基本属性读取:
- ID: 10001
- 姓名: 王小明
- 年龄: 25
- 薪资 (double): 15000.5
- 薪资 (BigDecimal): 15000.50
- 是否活跃: true
日期/时间属性读取:
- 入职日期: 2022-08-15
- 最后登录时间: Wed Aug 20 15:00:00 CST 2024 // 具体时间取决于执行时区
带默认值的属性读取:
- 职位: 普通员工
- 描述: 无描述
嵌套对象属性读取:
- 部门名称: 研发部
- 部门位置: A座3层
属性存在性检查:
- 是否包含 'email' 属性: false
- 是否包含 'department' 属性: true
使用 get 获取原始值:
- 年龄 (原始类型): Integer
- 部门 (原始类型): JSONObject
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
核心API说明:
- 类型安全的
getXXXValue
/getXXX
方法:getString(String key)
getIntValue(String key)
/getInteger(String key)
getLongValue(String key)
/getLong(String key)
getDoubleValue(String key)
/getDouble(String key)
getBooleanValue(String key)
/getBoolean(String key)
getBigDecimal(String key)
getDate(String key)
getJSONObject(String key)
getJSONArray(String key)
这些方法会尝试进行类型转换,如果无法转换或值为null
,通常返回相应类型的默认值(如0
,false
,null
)。
- 带默认值的
getXXX(key, defaultValue)
方法:getString(String key, String defaultValue)
getIntValue(String key, int defaultValue)
等 这是更安全的读取方式,推荐在不确定属性是否存在或可能为null
时使用。
containsKey(Object key)
:检查JSONObject
是否包含指定的键。get(Object key)
:获取指定键对应的值,返回Object
类型,需要调用者自行判断和转换类型。
# 2. JSON 数组的遍历与元素访问
JSONArray
的遍历方式多样,可以根据具体需求选择最合适的方法。
代码示例:
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
/**
* FastJson2 JSONArray 遍历与元素访问示例
* 演示遍历 JSONArray 及访问其中元素的多种方法。
*/
public class JsonArrayTraversalExample {
public static void main(String[] args) {
// 创建一个包含复杂学生对象的 JSON 数组字符串
String jsonString = "[" +
"{\"id\":1001,\"name\":\"张三\",\"score\":85.5,\"subjects\":[\"语文\",\"数学\",\"英语\"]}," +
"{\"id\":1002,\"name\":\"李四\",\"score\":92.0,\"isMonitor\":true,\"subjects\":[\"语文\",\"物理\",\"化学\"]}," +
"{\"id\":1003,\"name\":\"王五\",\"score\":78.0,\"subjects\":[\"历史\",\"地理\",\"政治\"]}," +
"\"备注信息\"," + // 数组中可以包含非 JSONObject 元素
"100" + // 也可以包含基本类型
"]";
// 将 JSON 字符串解析为 JSONArray
JSONArray studentsArray = JSONArray.parseArray(jsonString);
System.out.println("原始 JSONArray 包含 " + studentsArray.size() + " 个元素。");
// --- 遍历方法 ---
// 方法1: 使用传统 for 循环和索引访问
System.out.println("\n方法1: 传统 for 循环遍历");
for (int i = 0; i < studentsArray.size(); i++) {
Object element = studentsArray.get(i); // 获取原始 Object
// 需要判断元素类型再进行操作
if (element instanceof JSONObject) {
JSONObject student = (JSONObject) element; // 类型转换为 JSONObject
System.out.println(" 学生: " + student.getString("name") +
", 分数: " + student.getDoubleValue("score"));
} else if (element instanceof String) {
System.out.println(" 字符串元素: " + element);
} else if (element instanceof Number) {
System.out.println(" 数字元素: " + element);
} else {
System.out.println(" 其他类型元素: " + element);
}
}
// 方法2: 使用增强 for-each 循环 (语法更简洁)
System.out.println("\n方法2: 增强 for-each 循环遍历");
for (Object element : studentsArray) {
// 同样需要进行类型判断和转换
if (element instanceof JSONObject) {
JSONObject student = (JSONObject) element;
System.out.println(" ID: " + student.getIntValue("id") +
", 姓名: " + student.getString("name"));
} else {
// 处理其他类型...
}
}
// 方法3: 使用 Java 8 Stream API (适用于函数式编程风格)
System.out.println("\n方法3: Stream API 遍历 (筛选 JSONObject)");
studentsArray.stream()
.filter(obj -> obj instanceof JSONObject) // 筛选出 JSONObject 类型的元素
.map(obj -> (JSONObject) obj) // 转换为 JSONObject 流
.forEach(student -> { // 对每个 JSONObject 进行操作
System.out.println(" 姓名: " + student.getString("name") +
", 分数: " + student.getDoubleValue("score") +
", 是否班长: " + student.getBooleanValue("isMonitor", false)); // 使用带默认值的读取
// 访问嵌套数组
JSONArray subjects = student.getJSONArray("subjects");
if (subjects != null) {
System.out.print(" 科目: ");
subjects.forEach(subject -> System.out.print(subject + " "));
System.out.println();
}
});
// --- 访问特定元素 ---
// 获取第一个学生对象 (JSONObject)
if (studentsArray.size() > 0 && studentsArray.get(0) instanceof JSONObject) {
JSONObject firstStudent = studentsArray.getJSONObject(0);
System.out.println("\n访问第一个学生信息:");
System.out.println(" 姓名: " + firstStudent.getString("name"));
}
// 获取最后一个元素 (可能是任意类型)
if (!studentsArray.isEmpty()) {
Object lastElement = studentsArray.get(studentsArray.size() - 1);
System.out.println("\n访问最后一个元素 (类型: " + lastElement.getClass().getSimpleName() + "): " + lastElement);
}
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
输出结果:
原始 JSONArray 包含 5 个元素。
方法1: 传统 for 循环遍历
学生: 张三, 分数: 85.5
学生: 李四, 分数: 92.0
学生: 王五, 分数: 78.0
字符串元素: 备注信息
数字元素: 100
方法2: 增强 for-each 循环遍历
ID: 1001, 姓名: 张三
ID: 1002, 姓名: 李四
ID: 1003, 姓名: 王五
方法3: Stream API 遍历 (筛选 JSONObject)
姓名: 张三, 分数: 85.5, 是否班长: false
科目: 语文 数学 英语
姓名: 李四, 分数: 92.0, 是否班长: true
科目: 语文 物理 化学
姓名: 王五, 分数: 78.0, 是否班长: false
科目: 历史 地理 政治
访问第一个学生信息:
姓名: 张三
访问最后一个元素 (类型: Integer): 100
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
核心API说明:
get(int index)
:获取指定索引位置的元素,返回Object
类型。这是最通用的获取方法,但需要后续进行类型判断和转换。getJSONObject(int index)
/getJSONArray(int index)
/getString(int index)
等:获取指定索引位置的元素,并期望它是特定类型。如果类型不匹配,行为可能因 FastJson2 版本和配置而异(可能抛异常或返回null
)。size()
:获取数组中元素的数量。isEmpty()
:判断数组是否为空。stream()
:将JSONArray
转换为 Java 8Stream
,方便使用流式 API 进行过滤、映射、聚合等操作。
注意:遍历 JSONArray
时,由于其元素可以是任意类型,进行类型判断(instanceof
)通常是必要的,以避免 ClassCastException
。
# 四、JSON 字符串与对象转换(序列化与反序列化)
这是 FastJson2 最核心的功能之一:在 JSON 字符串表示与结构化对象(JSONObject
/JSONArray
或自定义的 Java POJO 类)之间进行转换。
# 1. JSON 字符串与 JSONObject/JSONArray 互转
这是处理原始 JSON 字符串或将内部 JSON 结构转换为字符串的基础操作。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONException; // 用于捕获解析异常
/**
* FastJson2 JSON 字符串与 JSONObject/JSONArray 互转示例
* 演示如何在 JSON 字符串和 FastJson2 的核心对象模型之间进行转换。
*/
public class JsonStringConversionExample {
public static void main(String[] args) {
// --- JSONObject 与 JSON 字符串互转 ---
// 1. 将 JSONObject 对象序列化为 JSON 字符串
JSONObject userObject = new JSONObject();
userObject.put("id", 10086);
userObject.put("name", "张三");
userObject.put("email", "zhangsan@example.com");
userObject.put("age", 28);
// 方法一:调用 JSONObject 的 toString() 方法
String userJsonString1 = userObject.toString();
System.out.println("JSONObject.toString() 转字符串:\n" + userJsonString1);
// 方法二:使用 JSON.toJSONString() 静态方法 (更通用,推荐)
String userJsonString2 = JSON.toJSONString(userObject);
System.out.println("\nJSON.toJSONString() 转字符串:\n" + userJsonString2);
// 2. 将 JSON 字符串反序列化为 JSONObject 对象
String jsonStr = "{\"id\":10087,\"name\":\"李四\",\"email\":\"lisi@example.com\",\"age\":30,\"isVerified\":true}";
try {
// 使用 JSONObject.parseObject() 静态方法
JSONObject parsedObject = JSONObject.parseObject(jsonStr);
System.out.println("\nJSON 字符串成功反序列化为 JSONObject:");
System.out.println("- 用户 ID: " + parsedObject.getIntValue("id"));
System.out.println("- 用户名: " + parsedObject.getString("name"));
System.out.println("- 是否已验证: " + parsedObject.getBooleanValue("isVerified"));
} catch (JSONException e) {
System.err.println("\nJSON 字符串解析为 JSONObject 时发生错误: " + e.getMessage());
}
// --- JSONArray 与 JSON 字符串互转 ---
// 3. 将 JSONArray 对象序列化为 JSON 字符串
JSONArray cityArray = JSONArray.of("北京", "上海", "广州", "深圳"); // 使用静态工厂方法创建
// 方法一:调用 JSONArray 的 toString() 方法
String cityJsonString1 = cityArray.toString();
System.out.println("\nJSONArray.toString() 转字符串:\n" + cityJsonString1);
// 方法二:使用 JSON.toJSONString() 静态方法
String cityJsonString2 = JSON.toJSONString(cityArray);
System.out.println("\nJSON.toJSONString() 转字符串:\n" + cityJsonString2);
// 4. 将 JSON 字符串反序列化为 JSONArray 对象
String arrayJsonStr = "[\"成都\",\"重庆\",\"武汉\",\"杭州\", 123, true]"; // 包含混合类型
try {
// 使用 JSONArray.parseArray() 静态方法
JSONArray parsedArray = JSONArray.parseArray(arrayJsonStr);
System.out.println("\nJSON 字符串成功反序列化为 JSONArray:");
System.out.println("- 数组大小: " + parsedArray.size());
System.out.println("- 第一个元素: " + parsedArray.getString(0));
System.out.println("- 最后一个元素类型: " + parsedArray.get(parsedArray.size() - 1).getClass().getSimpleName());
} catch (JSONException e) {
System.err.println("\nJSON 字符串解析为 JSONArray 时发生错误: " + e.getMessage());
}
// 5. 处理格式错误的 JSON 字符串
String invalidJson = "{\"name\":\"test\", age:30}"; // age 没有引号,格式错误
try {
JSONObject.parseObject(invalidJson);
} catch (JSONException e) {
System.err.println("\n尝试解析格式错误的 JSON 时捕获到异常: " + e.getMessage());
}
}
}
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
71
72
73
74
75
76
77
输出结果:
JSONObject.toString() 转字符串:
{"id":10086,"name":"张三","email":"zhangsan@example.com","age":28}
JSON.toJSONString() 转字符串:
{"id":10086,"name":"张三","email":"zhangsan@example.com","age":28}
JSON 字符串成功反序列化为 JSONObject:
- 用户 ID: 10087
- 用户名: 李四
- 是否已验证: true
JSONArray.toString() 转字符串:
["北京","上海","广州","深圳"]
JSON.toJSONString() 转字符串:
["北京","上海","广州","深圳"]
JSON 字符串成功反序列化为 JSONArray:
- 数组大小: 6
- 第一个元素: 成都
- 最后一个元素类型: Boolean
尝试解析格式错误的 JSON 时捕获到异常: syntax error, expect :, actual error, pos 17, fastjson-version 2.0.26 // 异常信息可能略有不同
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
核心API说明:
- 序列化 (对象 -> 字符串):
JSONObject.toString()
/JSONArray.toString()
:对象自身的方法,输出紧凑 JSON 字符串。JSON.toJSONString(Object object)
:推荐的静态方法,适用于任何 Java 对象(包括JSONObject
,JSONArray
, POJO,List
,Map
等),通用性更强。
- 反序列化 (字符串 -> 对象):
JSONObject.parseObject(String text)
:静态方法,将符合 JSON 对象格式的字符串解析为JSONObject
。JSONArray.parseArray(String text)
:静态方法,将符合 JSON 数组格式的字符串解析为JSONArray
。JSON.parse(String text)
:通用的静态方法,根据 JSON 字符串的根是{}
还是[]
自动返回JSONObject
或JSONArray
(返回类型是Object
,需要强转)。
异常处理:解析格式不正确的 JSON 字符串时,FastJson2 会抛出 JSONException
或其子类异常,应进行适当的 try-catch
处理。
# 2. JSON 与 Java 对象互转(POJO 序列化与反序列化)
这是开发中最常用的场景:将 JSON 数据直接映射到定义好的 Java Bean (POJO - Plain Old Java Object),或者反过来将 Java 对象转换为 JSON 字符串,通常用于 API 的请求响应、数据存储等。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField; // 引入 FastJson2 注解
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* FastJson2 JSON 与 Java POJO 互转示例
* 演示 JSON 字符串与自定义 Java 对象之间的序列化和反序列化。
*/
public class JsonJavaObjectConversionExample {
public static void main(String[] args) {
// --- Java 对象序列化为 JSON 字符串 ---
// 1. 创建一个复杂的 User 对象实例
User user = new User();
user.setId(10001);
user.setUsername("zhangsan_vip");
user.setRealName("张三");
user.setAge(28);
user.setEmail("zhangsan@example.com");
user.setCreateTime(new Date()); // 使用当前时间
user.setActive(true);
user.setSalary(18000.0); // 注意:此字段在 User 类中被 @JSONField(serialize = false) 标记
// 创建地址对象
Address address = new Address();
address.setProvince("北京市");
address.setCity("北京市");
address.setDistrict("海淀区");
address.setStreet("中关村大街1号");
address.setPostCode("100081");
user.setAddress(address); // 设置嵌套对象
// 创建角色列表
List<String> roles = new ArrayList<>();
roles.add("admin");
roles.add("editor");
user.setRoles(roles); // 设置集合属性
// 使用 JSON.toJSONString() 将 User 对象序列化为 JSON 字符串
String userJsonString = JSON.toJSONString(user);
System.out.println("Java 对象序列化为 JSON 字符串:");
System.out.println(userJsonString);
// 注意:输出的 JSON 中不应包含 salary 字段,且 createTime 可能是时间戳或默认格式字符串
// --- JSON 字符串反序列化为 Java 对象 ---
// 2. 准备一个 JSON 字符串,用于反序列化
String userJsonInput = "{"
+ "\"id\": 10002,"
+ "\"user_name\": \"lisi_test\"," // JSON 中的字段名与 Java 属性名不同
+ "\"real_name\": \"李四\","
+ "\"age\": 30,"
+ "\"email\": \"lisi@example.com\","
+ "\"creation_ts\": 1678886400000," // 使用时间戳表示日期,字段名也不同
+ "\"active\": false,"
+ "\"salary\": 20000.0," // JSON 中包含 salary,但反序列化时会被忽略
+ "\"address\": {"
+ "\"province\": \"上海市\","
+ "\"city\": \"上海市\","
+ "\"district\": \"浦东新区\","
+ "\"street\": \"张江高科1号\","
+ "\"zip_code\": \"200120\"" // 邮编字段名不同
+ "},"
+ "\"roles\": [\"user\", \"tester\"],"
+ "\"extra_info\": \"此字段在User类中不存在\"" // 额外的字段
+ "}";
try {
// 使用 JSON.parseObject() 将 JSON 字符串反序列化为 User 对象
// 可以传入 Feature 参数来控制反序列化行为,例如忽略未知字段
// FastJson2 默认行为比较宽松,通常会自动忽略未知字段
User parsedUser = JSON.parseObject(userJsonInput, User.class);
// 输出反序列化后的 User 对象信息
System.out.println("\nJSON 字符串成功反序列化为 Java 对象:");
System.out.println("- 用户 ID: " + parsedUser.getId());
System.out.println("- 用户名: " + parsedUser.getUsername()); // 成功通过 @JSONField(name="user_name") 映射
System.out.println("- 真实姓名: " + parsedUser.getRealName()); // 成功通过 @JSONField(name="real_name") 映射
System.out.println("- 年龄: " + parsedUser.getAge());
System.out.println("- 邮箱: " + parsedUser.getEmail());
System.out.println("- 创建时间: " + parsedUser.getCreateTime()); // 成功通过 @JSONField(name="creation_ts") 和 format/millis 映射
System.out.println("- 是否活跃: " + parsedUser.isActive());
System.out.println("- 薪水: " + parsedUser.getSalary()); // 反序列化时被忽略,应为 0.0
// 访问嵌套对象 Address
Address parsedAddress = parsedUser.getAddress();
if (parsedAddress != null) {
System.out.println("- 地址: " + parsedAddress.getProvince() + parsedAddress.getCity() +
parsedAddress.getDistrict() + parsedAddress.getStreet());
System.out.println("- 邮编: " + parsedAddress.getPostCode()); // 成功通过 @JSONField(name="zip_code") 映射
}
// 访问集合属性 Roles
List<String> parsedRoles = parsedUser.getRoles();
if (parsedRoles != null && !parsedRoles.isEmpty()) {
System.out.print("- 角色: ");
parsedRoles.forEach(role -> System.out.print(role + " "));
System.out.println();
}
} catch (JSONException e) {
System.err.println("\nJSON 反序列化为 Java 对象时出错: " + e.getMessage());
}
}
/**
* 用户 POJO 类
* 使用 @JSONField 注解来自定义序列化/反序列化行为
*/
public static class User {
// 默认情况下,FastJson2 会自动匹配同名或驼峰/下划线转换的字段
private int id;
@JSONField(name = "user_name") // 指定 JSON 中的字段名为 user_name
private String username;
@JSONField(name = "real_name") // 指定 JSON 中的字段名为 real_name
private String realName;
private int age;
private String email;
// 指定 JSON 中的字段名为 creation_ts,并指定日期格式为毫秒时间戳
@JSONField(name = "creation_ts", format = "millis")
private Date createTime;
private boolean active;
// serialize = false: 序列化时忽略此字段
// deserialize = false: 反序列化时忽略此字段 (默认值通常为 true)
@JSONField(serialize = false, deserialize = false)
private double salary;
private Address address; // 嵌套的 POJO 对象
private List<String> roles; // 集合类型的属性
// Getter 和 Setter 方法是必需的,FastJson2 通过它们访问属性
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getRealName() { return realName; }
public void setRealName(String realName) { this.realName = realName; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public boolean isActive() { return active; }
public void setActive(boolean active) { this.active = active; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public List<String> getRoles() { return roles; }
public void setRoles(List<String> roles) { this.roles = roles; }
}
/**
* 地址 POJO 类
*/
public static class Address {
private String province;
private String city;
private String district;
private String street;
@JSONField(name = "zip_code") // 映射 JSON 中的 zip_code 字段
private String postCode;
// Getters and Setters
public String getProvince() { return province; }
public void setProvince(String province) { this.province = province; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getDistrict() { return district; }
public void setDistrict(String district) { this.district = district; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
public String getPostCode() { return postCode; }
public void setPostCode(String postCode) { this.postCode = postCode; }
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
输出结果:
Java 对象序列化为 JSON 字符串:
{"active":true,"address":{"city":"北京市","district":"海淀区","postCode":"100081","province":"北京市","street":"中关村大街1号"},"age":28,"creation_ts":1692516000000,"email":"zhangsan@example.com","id":10001,"real_name":"张三","roles":["admin","editor"],"user_name":"zhangsan_vip"}
JSON 字符串成功反序列化为 Java 对象:
- 用户 ID: 10002
- 用户名: lisi_test
- 真实姓名: 李四
- 年龄: 30
- 邮箱: lisi@example.com
- 创建时间: Thu Mar 16 00:00:00 CST 2023 // 具体显示格式取决于 Date.toString()
- 是否活跃: false
- 薪水: 0.0
- 地址: 上海市上海市浦东新区张江高科1号
- 邮编: 200120
- 角色: user tester
2
3
4
5
6
7
8
9
10
11
12
13
14
15
核心API说明:
JSON.toJSONString(Object object)
:将任意 Java 对象(POJO、List、Map 等)序列化为 JSON 字符串。JSON.parseObject(String text, Class<T> clazz)
:将 JSON 字符串反序列化为指定Class
类型的 Java 对象。FastJson2 会自动根据类定义匹配 JSON 字段并填充属性值。
POJO 类要求:
- 通常需要提供一个无参构造函数(public 或 private 都可以)。
- 需要为需要序列化/反序列化的属性提供公共的 Getter 和 Setter 方法(或者属性是 public 的,但不推荐)。FastJson2 默认通过这些方法来读写属性值。
@JSONField
注解:
name
: 指定该 Java 属性在 JSON 字符串中对应的字段名。用于解决命名不一致(如 Java 驼峰userName
vs JSON 下划线user_name
)。format
: 指定日期/时间类型的格式化模式(如"yyyy-MM-dd HH:mm:ss"
)或特殊值(如"millis"
表示毫秒时间戳,"iso8601"
等)。serialize
: 布尔值,false
表示序列化时忽略该字段。deserialize
: 布尔值,false
表示反序列化时忽略该字段。ordinal
: 指定序列化时字段的输出顺序(数字越小越靠前)。
# 五、高级应用与处理技巧
FastJson2 不仅仅是简单的转换工具,还提供了许多高级功能来满足复杂场景的需求。
# 1. JSON 数据的格式化输出(Pretty Print)
为了提高 JSON 数据的可读性,尤其是在日志记录、调试或配置文件展示时,FastJson2 支持将其格式化(美化)输出,自动添加缩进和换行。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter; // 引入 JSONWriter
/**
* FastJson2 JSON 格式化输出示例
* 演示如何使用 PrettyFormat 特性美化 JSON 输出。
*/
public class JsonFormattingExample {
public static void main(String[] args) {
// 创建一个结构复杂的 JSONObject 用于演示
JSONObject company = new JSONObject();
company.put("name", "ABC 科技股份有限公司");
company.put("foundingYear", 2010);
company.put("isListed", true);
company.put("registeredCapital", "1亿人民币"); // 字符串类型
// 添加地址对象
JSONObject address = new JSONObject()
.fluentPut("country", "中国")
.fluentPut("province", "广东")
.fluentPut("city", "深圳")
.fluentPut("street", "科技园南区")
.fluentPut("zip", "518057");
company.put("headquartersAddress", address);
// 添加部门列表 (JSONArray)
JSONArray departments = new JSONArray();
// 研发部门
JSONObject devDept = new JSONObject()
.fluentPut("name", "核心研发部")
.fluentPut("manager", "张工")
.fluentPut("employeeCount", 150);
// 添加研发部门的团队列表
JSONArray devTeams = JSONArray.of("平台架构组", "数据智能组", "前端工程组", "移动开发组");
devDept.put("teams", devTeams);
// 市场部门
JSONObject marketDept = new JSONObject()
.fluentPut("name", "全球市场部")
.fluentPut("manager", "李总")
.fluentPut("employeeCount", 80);
marketDept.put("overseasOffices", JSONArray.of("硅谷", "伦敦", "新加坡")); // 添加海外办事处
departments.add(devDept);
departments.add(marketDept);
company.put("departments", departments);
// 1. 默认输出 (紧凑格式,无缩进和换行)
String defaultJson = company.toString();
System.out.println("--- 默认 JSON 输出 (无格式化) ---");
System.out.println(defaultJson);
// 2. 使用 JSONWriter.Feature.PrettyFormat 进行格式化输出
// 将 Feature 作为参数传递给 JSON.toJSONString()
String prettyJson = JSON.toJSONString(company, JSONWriter.Feature.PrettyFormat);
System.out.println("\n--- 使用 PrettyFormat 格式化后的 JSON 输出 ---");
System.out.println(prettyJson);
// 也可以格式化 JSONArray
JSONArray simpleArray = JSONArray.of(1, "two", true, null, JSONObject.of("key", "value"));
String prettyArrayJson = JSON.toJSONString(simpleArray, JSONWriter.Feature.PrettyFormat);
System.out.println("\n--- 格式化后的 JSONArray 输出 ---");
System.out.println(prettyArrayJson);
}
}
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
输出结果:
--- 默认 JSON 输出 (无格式化) ---
{"name":"ABC 科技股份有限公司","foundingYear":2010,"isListed":true,"registeredCapital":"1亿人民币","headquartersAddress":{"country":"中国","province":"广东","city":"深圳","street":"科技园南区","zip":"518057"},"departments":[{"name":"核心研发部","manager":"张工","employeeCount":150,"teams":["平台架构组","数据智能组","前端工程组","移动开发组"]},{"name":"全球市场部","manager":"李总","employeeCount":80,"overseasOffices":["硅谷","伦敦","新加坡"]}]}
--- 使用 PrettyFormat 格式化后的 JSON 输出 ---
{
"name":"ABC 科技股份有限公司",
"foundingYear":2010,
"isListed":true,
"registeredCapital":"1亿人民币",
"headquartersAddress":{
"country":"中国",
"province":"广东",
"city":"深圳",
"street":"科技园南区",
"zip":"518057"
},
"departments":[
{
"name":"核心研发部",
"manager":"张工",
"employeeCount":150,
"teams":[
"平台架构组",
"数据智能组",
"前端工程组",
"移动开发组"
]
},
{
"name":"全球市场部",
"manager":"李总",
"employeeCount":80,
"overseasOffices":[
"硅谷",
"伦敦",
"新加坡"
]
}
]
}
--- 格式化后的 JSONArray 输出 ---
[
1,
"two",
true,
null,
{
"key":"value"
}
]
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
核心API说明:
JSON.toJSONString(Object object, JSONWriter.Feature... features)
:这是进行格式化输出的关键方法。JSONWriter.Feature.PrettyFormat
:这是一个枚举常量,代表“漂亮打印”的特性。启用它后,输出的 JSON 字符串会包含适当的缩进和换行,大大提高可读性。
# 2. JSON 与 Map 互转(灵活处理动态数据)
当 JSON 的结构事先不确定,或者需要以键值对的方式灵活处理数据时,将 JSON 与 Java Map
进行互转是非常方便的策略。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray; // 需要引入 JSONArray
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.TypeReference; // 用于处理泛型
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.List; // 需要引入 List
/**
* FastJson2 JSON 与 Map 互转示例
* 演示如何在 JSON 字符串/对象与 Java Map 之间进行灵活转换。
*/
public class JsonMapConversionExample {
public static void main(String[] args) {
// --- Map 序列化为 JSON 字符串 ---
// 1. 创建一个嵌套的 Map 结构 (使用 LinkedHashMap 保持插入顺序)
Map<String, Object> configMap = new LinkedHashMap<>();
configMap.put("appName", "智能配置中心");
configMap.put("version", "2.1.0");
configMap.put("debugMode", true);
configMap.put("threadPoolSize", 16);
// 嵌套的数据库配置 Map
Map<String, Object> databaseConfig = new HashMap<>();
databaseConfig.put("url", "jdbc:mysql://localhost:3306/configdb");
databaseConfig.put("username", "config_user");
databaseConfig.put("password", null); // 显式设置 null 值
databaseConfig.put("connectionTimeout", 30000);
configMap.put("database", databaseConfig);
// 包含数组的配置项
List<String> supportedLanguages = List.of("Java", "Python", "Go");
configMap.put("supportedLanguages", supportedLanguages);
// 将 Map 序列化为 JSON 字符串,并启用 PrettyFormat 和 WriteMapNullValue
String mapJsonString = JSON.toJSONString(configMap,
JSONWriter.Feature.PrettyFormat, // 格式化输出
JSONWriter.Feature.WriteMapNullValue // 保留 Map 中的 null 值 (如 password)
);
System.out.println("--- Map 序列化为 JSON 字符串 (保留 null 值并格式化) ---");
System.out.println(mapJsonString);
// --- JSON 字符串反序列化为 Map ---
// 2. 准备一个 JSON 字符串
String serverConfigJson = "{"
+ "\"serverName\": \"API 网关\", "
+ "\"listenPort\": 8888, "
+ "\"enableHttps\": false, "
+ "\"requestTimeoutMillis\": 5000, "
+ "\"rateLimit\": {" // 嵌套对象
+ "\"requestsPerSecond\": 100, "
+ "\"burstCapacity\": 200"
+ "}, "
+ "\"enabledFeatures\": [\"Authentication\", \"Logging\", \"RateLimiting\"]" // 数组
+ "}";
// 使用 TypeReference 将 JSON 字符串反序列化为 Map<String, Object>
// TypeReference 用于在运行时保留泛型信息
Map<String, Object> parsedMap = JSON.parseObject(serverConfigJson,
new TypeReference<Map<String, Object>>() {});
System.out.println("\n--- JSON 字符串反序列化为 Map ---");
System.out.println("服务器名称: " + parsedMap.get("serverName")); // 获取 String 值
System.out.println("监听端口: " + parsedMap.get("listenPort")); // 获取 Integer/Long 值
System.out.println("是否启用 HTTPS: " + parsedMap.get("enableHttps")); // 获取 Boolean 值
// 访问嵌套 Map (注意:FastJson2 可能将其解析为 JSONObject,需要转换)
Object rateLimitObj = parsedMap.get("rateLimit");
if (rateLimitObj instanceof Map) { // 检查类型
@SuppressWarnings("unchecked") // 抑制类型转换警告
Map<String, Object> rateLimitMap = (Map<String, Object>) rateLimitObj;
System.out.println("速率限制 (每秒请求数): " + rateLimitMap.get("requestsPerSecond"));
} else if (rateLimitObj instanceof JSONObject) { // 也可能是 JSONObject
JSONObject rateLimitJsonObj = (JSONObject) rateLimitObj;
System.out.println("速率限制 (每秒请求数): " + rateLimitJsonObj.getIntValue("requestsPerSecond"));
}
// 访问数组 (注意:FastJson2 可能将其解析为 JSONArray,需要转换)
Object featuresObj = parsedMap.get("enabledFeatures");
if (featuresObj instanceof List) { // 检查类型
@SuppressWarnings("unchecked")
List<String> featuresList = (List<String>) featuresObj;
System.out.print("启用的特性: ");
featuresList.forEach(feature -> System.out.print(feature + " "));
System.out.println();
} else if (featuresObj instanceof JSONArray) { // 也可能是 JSONArray
JSONArray featuresArray = (JSONArray) featuresObj;
System.out.print("启用的特性: ");
featuresArray.forEach(feature -> System.out.print(feature + " "));
System.out.println();
}
// --- JSONObject 与 Map 互转 ---
// 3. 将 Map 转换为 JSONObject
Map<String, Object> simpleMap = Map.of("key1", "value1", "key2", 123, "key3", true);
JSONObject jsonObjectFromMap = new JSONObject(simpleMap); // 使用 Map 构造 JSONObject
jsonObjectFromMap.put("newKey", "newValue"); // 可以继续操作 JSONObject
System.out.println("\n--- Map 转换为 JSONObject ---");
System.out.println(jsonObjectFromMap.toJSONString());
// 4. 将 JSONObject 转换为 Map
JSONObject someJsonObject = JSONObject.of("propA", "abc", "propB", 456);
Map<String, Object> mapFromJsonObject = someJsonObject.toJavaObject(Map.class); // 使用 toJavaObject 转换
System.out.println("\n--- JSONObject 转换为 Map ---");
System.out.println("Map 内容: " + mapFromJsonObject);
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
输出结果:
--- Map 序列化为 JSON 字符串 (保留 null 值并格式化) ---
{
"appName":"智能配置中心",
"version":"2.1.0",
"debugMode":true,
"threadPoolSize":16,
"database":{
"password":null,
"url":"jdbc:mysql://localhost:3306/configdb",
"username":"config_user",
"connectionTimeout":30000
},
"supportedLanguages":[
"Java",
"Python",
"Go"
]
}
--- JSON 字符串反序列化为 Map ---
服务器名称: API 网关
监听端口: 8888
是否启用 HTTPS: false
速率限制 (每秒请求数): 100
启用的特性: Authentication Logging RateLimiting
--- Map 转换为 JSONObject ---
{"key1":"value1","key2":123,"key3":true,"newKey":"newValue"}
--- JSONObject 转换为 Map ---
Map 内容: {propA=abc, propB=456}
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
核心API说明:
JSON.toJSONString(Map map, JSONWriter.Feature... features)
:将Map
序列化为 JSON 字符串。可以通过JSONWriter.Feature.WriteMapNullValue
控制是否输出null
值的键。JSON.parseObject(String text, TypeReference<T> type)
:将 JSON 字符串反序列化为指定的泛型类型,如TypeReference<Map<String, Object>>
。这是处理泛型Map
的标准方式。new JSONObject(Map<String, Object> map)
:使用Map
来构造一个新的JSONObject
实例。JSONObject.toJavaObject(Class<T> clazz)
:将JSONObject
转换为指定类型的 Java 对象,可以传入Map.class
将其转为Map
。
注意:当 JSON 字符串反序列化为 Map<String, Object>
时,嵌套的 JSON 对象默认可能会被解析为 JSONObject
(或 LinkedHashMap
),JSON 数组则可能被解析为 JSONArray
(或 ArrayList
)。在访问这些嵌套结构时,需要进行相应的类型检查和转换。
# 3. JSON 数组与 List 互转(批量数据处理)
这在处理 API 返回的列表数据或需要将 Java 集合序列化为 JSON 数组时非常常见。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.TypeReference;
import com.alibaba.fastjson2.JSONWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; // 需要引入 Map
/**
* FastJson2 JSON 数组与 List 互转示例
* 演示如何在 JSON 数组字符串和 Java List 集合之间进行转换。
*/
public class JsonListConversionExample {
public static void main(String[] args) {
// --- List 序列化为 JSON 数组字符串 ---
// 1. 创建一个包含 Product 对象的 List
List<Product> productList = new ArrayList<>();
productList.add(new Product(1001, "笔记本电脑 Pro", 7999.00, true));
productList.add(new Product(1002, "旗舰智能手机", 4999.00, true));
productList.add(new Product(1003, "降噪无线耳机", 1299.00, true));
productList.add(new Product(1004, "RGB 机械键盘", 599.00, false)); // available 为 false
// 使用 JSON.toJSONString 将 List<Product> 序列化为 JSON 数组字符串
String productListJson = JSON.toJSONString(productList);
System.out.println("--- List<Product> 序列化为 JSON 数组 ---");
System.out.println(productListJson);
// 格式化输出 List
String prettyProductListJson = JSON.toJSONString(productList, JSONWriter.Feature.PrettyFormat);
System.out.println("\n--- 格式化输出 List<Product> ---");
System.out.println(prettyProductListJson);
// --- JSON 数组字符串反序列化为 List ---
// 2. 准备一个包含产品信息的 JSON 数组字符串
String productsJsonInput = "["
+ "{\"id\":2001,\"productName\":\"高性能平板\",\"price\":3299.0,\"inStock\":true}," // 字段名与 Product 类不同
+ "{\"id\":2002,\"productName\":\"4K 显示器\",\"price\":1499.0,\"inStock\":true},"
+ "{\"id\":2003,\"productName\":\"无线游戏鼠标\",\"price\":299.0,\"inStock\":false}"
+ "]";
// 使用 JSON.parseArray 将 JSON 数组字符串反序列化为 List<Product>
// 需要 Product 类有相应的 Getter/Setter 和无参构造函数
// FastJson2 会尝试自动匹配字段名(驼峰/下划线)
List<Product> parsedProducts = JSON.parseArray(productsJsonInput, Product.class);
System.out.println("\n--- JSON 数组反序列化为 List<Product> ---");
if (parsedProducts != null) {
parsedProducts.forEach(product ->
System.out.println("- ID: " + product.getId() +
", 名称: " + product.getName() + // 假设 getName() 对应 productName
", 价格: ¥" + product.getPrice() +
(product.isAvailable() ? " (有货)" : " (缺货)")) // 假设 isAvailable() 对应 inStock
);
}
// 3. 反序列化为 List<Map<String, Object>> (处理结构不固定的数组)
String usersJson = "["
+ "{\"userId\": 1, \"username\": \"Alice\", \"tags\": [\"Java\", \"Spring\"]},"
+ "{\"userId\": 2, \"username\": \"Bob\", \"city\": \"New York\"}" // 结构不同
+ "]";
// 使用 TypeReference 来指定泛型类型 List<Map<String, Object>>
List<Map<String, Object>> userMapList = JSON.parseObject(usersJson,
new TypeReference<List<Map<String, Object>>>() {});
System.out.println("\n--- JSON 数组反序列化为 List<Map<String, Object>> ---");
if (userMapList != null) {
userMapList.forEach(userMap -> {
System.out.println("用户 Map: " + userMap);
// 可以进一步处理 Map 中的数据
System.out.println(" 用户名: " + userMap.get("username"));
});
}
// --- JSONArray 与 List 互转 ---
// 4. 将 List 转换为 JSONArray
List<String> simpleList = List.of("One", "Two", "Three");
JSONArray jsonArrayFromList = new JSONArray(simpleList); // 使用 List 构造 JSONArray
System.out.println("\n--- List<String> 转换为 JSONArray ---");
System.out.println(jsonArrayFromList.toJSONString());
// 5. 将 JSONArray 转换为 List
JSONArray someJsonArray = JSONArray.of("A", 1, true, null);
// 使用 toJavaList 指定转换的目标元素类型
List<Object> listFromJSONArray = someJsonArray.toJavaList(Object.class); // 转为 List<Object>
List<String> stringListFromJSONArray = someJsonArray.toJavaList(String.class); // 尝试转为 List<String> (非字符串元素会尝试转换或报错/null)
System.out.println("\n--- JSONArray 转换为 List ---");
System.out.println("转换为 List<Object>: " + listFromJSONArray);
System.out.println("尝试转换为 List<String>: " + stringListFromJSONArray); // 注意类型转换结果
}
/**
* 产品 POJO 类
*/
public static class Product {
private int id;
// 假设 JSON 中的 productName 对应这里的 name
@JSONField(name = "productName")
private String name;
private double price;
// 假设 JSON 中的 inStock 对应这里的 available
@JSONField(name = "inStock")
private boolean available;
// 无参构造函数 (FastJson 反序列化需要)
public Product() {}
// 有参构造函数 (方便创建对象)
public Product(int id, String name, double price, boolean available) {
this.id = id;
this.name = name;
this.price = price;
this.available = available;
}
// Getters and Setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public boolean isAvailable() { return available; }
public void setAvailable(boolean available) { this.available = available; }
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
输出结果:
--- List<Product> 序列化为 JSON 数组 ---
[{"id":1001,"inStock":true,"price":7999.0,"productName":"笔记本电脑 Pro"},{"id":1002,"inStock":true,"price":4999.0,"productName":"旗舰智能手机"},{"id":1003,"inStock":true,"price":1299.0,"productName":"降噪无线耳机"},{"id":1004,"inStock":false,"price":599.0,"productName":"RGB 机械键盘"}]
--- 格式化输出 List<Product> ---
[
{
"id":1001,
"inStock":true,
"price":7999.0,
"productName":"笔记本电脑 Pro"
},
{
"id":1002,
"inStock":true,
"price":4999.0,
"productName":"旗舰智能手机"
},
{
"id":1003,
"inStock":true,
"price":1299.0,
"productName":"降噪无线耳机"
},
{
"id":1004,
"inStock":false,
"price":599.0,
"productName":"RGB 机械键盘"
}
]
--- JSON 数组反序列化为 List<Product> ---
- ID: 2001, 名称: 高性能平板, 价格: ¥3299.0 (有货)
- ID: 2002, 名称: 4K 显示器, 价格: ¥1499.0 (有货)
- ID: 2003, 名称: 无线游戏鼠标, 价格: ¥299.0 (缺货)
--- JSON 数组反序列化为 List<Map<String, Object>> ---
用户 Map: {userId=1, username=Alice, tags=["Java", "Spring"]}
用户名: Alice
用户 Map: {userId=2, username=Bob, city=New York}
用户名: Bob
--- List<String> 转换为 JSONArray ---
["One","Two","Three"]
--- JSONArray 转换为 List ---
转换为 List<Object>: [A, 1, true, null]
尝试转换为 List<String>: [A, 1, true, null] // FastJson2 尝试转换,数字/布尔可能转为字符串,null 保持 null
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
核心API说明:
JSON.toJSONString(List<?> list, JSONWriter.Feature... features)
:将 JavaList
序列化为 JSON 数组字符串。JSON.parseArray(String text, Class<T> elementType)
:将 JSON 数组字符串反序列化为指定元素类型的List
,例如List<Product>
。JSON.parseObject(String text, TypeReference<T> type)
:用于反序列化为复杂的泛型List
,如List<Map<String, Object>>
或List<List<Integer>>
。new JSONArray(Collection<?> collection)
:使用 JavaCollection
(如List
) 来构造一个新的JSONArray
。JSONArray.toJavaList(Class<T> elementType)
:将JSONArray
转换为指定元素类型的List
。FastJson2 会尝试将数组中的每个元素转换为目标类型T
。
# 六、FastJson2 特性配置与性能优化
FastJson2 提供了丰富的 Feature
枚举,允许开发者精细地控制序列化(JSONWriter.Feature
)和反序列化(JSONReader.Feature
)的行为,以满足特定需求或进行性能调优。
代码示例:
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader; // 引入 JSONReader
import com.alibaba.fastjson2.JSONWriter; // 引入 JSONWriter
import com.alibaba.fastjson2.annotation.JSONField; // 引入 JSONField
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
/**
* FastJson2 Feature 配置与性能优化示例
* 演示如何使用 JSONWriter.Feature 和 JSONReader.Feature 来定制行为。
*/
public class JsonFeatureConfigExample {
public static void main(String[] args) {
// --- 序列化特性配置 (JSONWriter.Feature) ---
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", 1001);
dataMap.put("name", "测试数据");
dataMap.put("createTime", new Date());
dataMap.put("updateTime", null); // null 值
dataMap.put("description", ""); // 空字符串
dataMap.put("emptyList", new ArrayList<>()); // 空列表
dataMap.put("nullList", null); // null 列表
dataMap.put("rawValue", "{\"key\":\"value\"}"); // 包含 JSON 字符串的值
// 1. 默认序列化行为
String defaultJson = JSON.toJSONString(dataMap);
System.out.println("--- 默认序列化 ---");
System.out.println(defaultJson); // 通常:忽略 null 值, 不格式化, Date 输出为时间戳
// 2. 使用多个 Feature 定制序列化
String customJson = JSON.toJSONString(dataMap,
JSONWriter.Feature.PrettyFormat, // 格式化输出
JSONWriter.Feature.WriteMapNullValue, // 输出 Map 中的 null 值 (updateTime)
JSONWriter.Feature.WriteNullListAsEmpty, // 将为 null 的列表输出为空数组 [] (nullList)
JSONWriter.Feature.WriteNullStringAsEmpty,// 将为 null 的字符串输出为空字符串 "" (如果 description 为 null)
JSONWriter.Feature.WriteDateUseDateFormat, // 使用默认或指定的日期格式 (createTime)
JSONWriter.Feature.NotWriteEmptyArray, // 不输出空数组 (emptyList) - 注意与 WriteNullListAsEmpty 的区别
JSONWriter.Feature.WriteNonStringValueAsString // 将非字符串的基本类型值写为字符串 (id 会变成 "1001")
// JSONWriter.Feature.BeanToArray // (特殊) 将 Bean 序列化为数组形式
// JSONWriter.Feature.WriteRawValue // 直接输出标记为 raw 的字段值 (需要配合 @JSONField(serializeFeatures = ...))
);
System.out.println("\n--- 使用多个 Feature 定制序列化 ---");
System.out.println(customJson);
// 3. 全局配置日期格式 (影响 WriteDateUseDateFormat)
JSON.config( // 配置全局默认格式
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z"), // 设置日期格式
JSONWriter.Feature.WriteDateUseDateFormat // 确保该特性开启才能生效
);
// JSON.config(TimeZone.getTimeZone("UTC")); // 也可以配置全局时区
String globallyFormattedDateJson = JSON.toJSONString(dataMap, JSONWriter.Feature.WriteDateUseDateFormat);
System.out.println("\n--- 使用全局配置的日期格式序列化 ---");
System.out.println(globallyFormattedDateJson);
// 恢复默认配置,避免影响后续示例
JSON.config(JSON.createDateFormat(), JSONWriter.Feature.WriteDateUseDateFormat);
// --- 反序列化特性配置 (JSONReader.Feature) ---
// 4. 准备包含特殊情况的 JSON 字符串
String inputJson = "{"
+ "\"userId\": 1002, " // 与 POJO 字段名 id 不完全匹配
+ "\"UserName\": \"测试产品\", " // 大小写不匹配
+ "\"price\": 99.9, "
+ "\"extraField\": \"这个字段在 POJO 中不存在\", "
+ "\"isEnabled\": \"true\", " // 布尔值是字符串形式
+ "\"creationDate\": \"2023-01-01 10:00:00\"" // 日期字符串
+ "}";
System.out.println("\n--- 反序列化特性演示 ---");
try {
// 使用 Feature 定制反序列化行为
Product product = JSON.parseObject(inputJson, Product.class,
// 忽略 JSON 中存在但 Java 类中没有对应字段的属性 (FastJson2 默认通常已开启)
// JSONReader.Feature.IgnoreUnknownField, // 明确开启忽略未知字段
JSONReader.Feature.SupportSmartMatch, // 支持智能名称匹配 (userId -> id, UserName -> userName)
JSONReader.Feature.ErrorOnEnumNotMatch, // 如果枚举值不匹配则报错
JSONReader.Feature.ReadBooleanAsBoolean, // 尝试将非标量值(如字符串"true")转为布尔
JSONReader.Feature.FieldBased // (性能优化) 基于字段访问,可能更快但有局限性
// JSONReader.Feature.SupportArrayToBean // 支持将 JSON 数组映射到 Bean (需要注解配合)
);
System.out.println("成功解析 Product 对象:");
System.out.println(" ID: " + product.getId());
System.out.println(" Name: " + product.getName());
System.out.println(" Price: " + product.getPrice());
System.out.println(" Enabled: " + product.isEnabled()); // 来自 isEnabled 字符串
System.out.println(" Creation Date: " + product.getCreationDate()); // 自动解析日期字符串
} catch (Exception e) {
System.err.println("反序列化时发生错误: " + e.getMessage());
e.printStackTrace();
}
// 5. 性能相关特性 (FieldBased, UseNativeObject)
// 通常在大数据量解析时使用,可以提升性能,但可能有兼容性或功能限制
// 示例:JSON.parseObject(largeJson, MyClass.class, JSONReader.Feature.FieldBased, JSONReader.Feature.UseNativeObject);
// 具体效果需根据场景测试。
System.out.println("\n(性能特性 FieldBased 和 UseNativeObject 通常用于大数据量解析,此处不详细演示)");
}
/**
* 产品 POJO 类,用于反序列化测试
*/
public static class Product {
private int id;
private String name;
private double price;
private boolean isEnabled;
private Date creationDate;
// Getters and Setters...
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public boolean isEnabled() { return isEnabled; }
public void setEnabled(boolean enabled) { isEnabled = enabled; }
public Date getCreationDate() { return creationDate; }
public void setCreationDate(Date creationDate) { this.creationDate = creationDate; }
}
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
输出结果 (部分结果可能因执行环境和时间变化):
--- 默认序列化 ---
{"createTime":1692518400000,"emptyList":[],"id":1001,"name":"测试数据","rawValue":"{\"key\":\"value\"}","description":""}
--- 使用多个 Feature 定制序列化 ---
{
"id":"1001",
"name":"测试数据",
"createTime":"2024/08/20 17:00:00 +0800",
"updateTime":null,
"description":"",
"nullList":[]
}
--- 使用全局配置的日期格式序列化 ---
{"createTime":"2024/08/20 17:00:00 +0800","emptyList":[],"id":1001,"name":"测试数据","rawValue":"{\"key\":\"value\"}","description":""}
--- 反序列化特性演示 ---
成功解析 Product 对象:
ID: 1002
Name: 测试产品
Price: 99.9
Enabled: true
Creation Date: Sun Jan 01 10:00:00 CST 2023
(性能特性 FieldBased 和 UseNativeObject 通常用于大数据量解析,此处不详细演示)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
常用特性说明:
序列化特性 (
JSONWriter.Feature
):WriteMapNullValue
: 序列化Map
时,输出值为null
的键值对。WriteNullListAsEmpty
: 当List
或数组字段值为null
时,输出[]
而不是null
。WriteNullStringAsEmpty
: 当字符串字段值为null
时,输出""
而不是null
。WriteNullBooleanAsFalse
: 当布尔字段值为null
时,输出false
而不是null
。WriteNullNumberAsZero
: 当数字字段值为null
时,输出0
而不是null
。WriteDateUseDateFormat
: 使用JSON.config
配置的全局DateFormat
或@JSONField
指定的格式来序列化Date
对象,而不是默认的时间戳。PrettyFormat
: 格式化输出 JSON,带缩进和换行。WriteClassName
: (不推荐,有安全风险) 在 JSON 中输出类名信息。NotWriteEmptyArray
: 如果数组或List
为空,则不输出该字段。WriteNonStringValueAsString
: 将非字符串的基本类型(如数字、布尔)序列化为字符串形式(例如123
->"123"
)。WriteEnumsUsingName
: 使用枚举的name()
方法进行序列化(默认)。WriteEnumsUsingToString
: 使用枚举的toString()
方法进行序列化。BeanToArray
: 将 Java Bean 序列化为 JSON 数组形式(按字段顺序)。WriteRawValue
: 配合@JSONField(serializeFeatures = JSONWriter.Feature.WriteRawValue)
使用,直接输出字段的字符串值,不进行 JSON 转义(用于嵌入已有的 JSON 片段)。
反序列化特性 (
JSONReader.Feature
):SupportSmartMatch
: 支持智能字段名匹配,可以自动匹配驼峰与下划线风格(如userName
匹配user_name
),并忽略大小写差异。IgnoreUnknownField
: (默认开启) 忽略 JSON 中存在但 Java 类中没有对应字段的属性,不抛出异常。ErrorOnEnumNotMatch
: 当 JSON 中的值无法匹配到 Java 枚举常量时,抛出异常(默认可能为null
或不抛异常)。ReadNullStringAsEmpty
: 将 JSON 中的null
值反序列化为空字符串""
。ReadNullBooleanAsFalse
: 将null
反序列化为false
。ReadNullNumberAsZero
: 将null
反序列化为0
。ReadNullListAsEmpty
: 将null
反序列化为空List
或空数组。ReadBooleanAsBoolean
: 尝试将非布尔值(如字符串"true"
,"false"
, 数字1
,0
)也解析为布尔类型。FieldBased
: (性能优化) 使用基于字段(Field)的反射访问,而不是基于 Getter/Setter 方法。这通常更快,但如果类中有复杂的 Getter/Setter 逻辑,可能会导致行为不一致。需要类有无参构造函数。UseNativeObject
: (性能优化) 尽可能使用 FastJson2 内部优化的原生对象,减少创建标准 Java 对象的开销,通常与FieldBased
配合使用。SupportArrayToBean
: 允许将 JSON 数组反序列化为 Java Bean(需要配合@JSONField(deserializeFeatures = ...)
和字段顺序)。
配置方式:
- 单次调用时配置: 将
Feature
枚举常量作为可变参数传递给JSON.toJSONString()
或JSON.parseObject()
/JSON.parseArray()
方法。 - 全局配置: 使用
JSON.config(...)
方法设置全局默认的Feature
或DateFormat
、TimeZone
等。全局配置会影响所有未使用特定Feature
参数的调用。
通过合理配置这些 Feature
,可以使 FastJson2 的行为更符合项目需求,并在必要时提升处理性能。
总结
FastJson2 作为阿里巴巴对其经典 FastJson 库的全面升级,不仅继承了其易用性和丰富的功能,更在性能和安全性上迈出了巨大的步伐。它是现代 Java 应用中处理 JSON 数据的一个强大而高效的选择。
核心优势与功能回顾:
- 极致性能: FastJson2 在序列化和反序列化速度上通常优于 FastJson 1.x 及其他常见 Java JSON 库。
- 安全性提升: 彻底移除了
autoType
机制,从设计上规避了相关的反序列化漏洞风险。 - 易用的 API: 提供了
JSONObject
,JSONArray
以及静态JSON
工具类,API 设计直观,易于上手。- 轻松创建和操作
JSONObject
和JSONArray
。 - 方便地在 JSON 字符串、
JSONObject
/JSONArray
、Java POJO、Map
、List
之间进行转换。
- 轻松创建和操作
- 强大的 POJO 支持: 能够自动或通过
@JSONField
注解灵活地处理 Java Bean 与 JSON 之间的映射,支持嵌套对象和集合。 - 灵活的特性配置: 通过
JSONWriter.Feature
和JSONReader.Feature
,可以精细控制序列化和反序列化的各种行为,如 null 值处理、日期格式、字段名匹配、格式化输出等。 - 丰富的生态与扩展: 虽然是较新的版本,但其设计考虑了扩展性,并逐步完善生态支持。
无论是构建高性能的微服务、处理大规模数据交换、还是日常的 Web 开发,FastJson2 都提供了一个值得信赖且高效的 JSON 处理解决方案。掌握其核心用法和特性配置,将有助于提升 Java 应用的性能和开发效率。