Fastjson2 JSONPath 支持
作为 Java 开发者,处理 JSON 数据时常常需要从嵌套结构中提取特定字段。传统的做法是手动解析每一层,不仅代码冗长,而且容易出错。Fastjson2 提供的 JSONPath 支持,就像给 JSON 数据装上了导航仪,让你能像使用 XPath 操作 XML 一样,快速定位 JSON 中的任意节点。
什么是 JSONPath?
JSONPath 是一种查询 JSON 数据的表达式语言,它通过路径表达式来定位 JSON 节点。Fastjson2 不仅完整实现了 JSONPath 规范,还额外支持了一些实用特性。
快速上手
1. 添加依赖
首先确保项目中引入 Fastjson2:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.61</version>
</dependency>
2. 基础用法
假设我们有如下 JSON 数据:
{
"store": {
"book": [
{
"title": "Java 编程思想",
"price": 89.0,
"authors": ["Bruce Eckel"]
},
{
"title": "Effective Java",
"price": 68.0,
"authors": ["Joshua Bloch"]
}
],
"bicycle": {
"color": "red",
"price": 1999.0
}
}
}
通过json转字符串工具可以压缩json一行,放到下面jsonStr字符串使用。
获取所有书名
String jsonStr = "..."; // 上面 JSON 字符串
JSONObject obj = JSON.parseObject(jsonStr);
// 使用 JSONPath 提取所有书名
List<String> titles = (List<String>) JSONPath.eval(obj, "$.store.book[*].title");
System.out.println(titles); // ["Java 编程思想", "Effective Java"]
相关参数解释如下:
- $ 表示根节点
- .store.book 访问 store 对象下的 book 数组
- [*] 表示数组中的所有元素
- .title 获取每本书的 title 属性
条件过滤
获取价格大于 70 的书籍:
// 过滤条件
List<JSONObject> expensiveBooks = (List<JSONObject>) JSONPath.eval(
obj, "$.store.book[?(@.price > 70)]"
);
expensiveBooks.forEach(book ->
System.out.println(book.getString("title"))
);
// 输出: Java 编程思想
参数解释:
- [?(@.price > 70)] 是一个过滤表达式
- ?() 表示条件判断
- @ 代表当前正在处理的数组元素
- .price > 70 条件是书的 price 属性大于 70
获取特定位置的元素
获取第一本书的作者:
String firstAuthor = (String) JSONPath.eval(obj, "$.store.book[0].authors[0]");
System.out.println(firstAuthor); // Bruce Eckel
参数解释
- $.store.book[0] 访问 book 数组的第一个元素(索引从 0 开始)
- .authors[0] 访问该书的 authors 数组的第一个作者
进阶特性
1. 通配符与深度查询
// 查找所有价格字段(不限层级)
List<Double> allPrices = (List<Double>) JSONPath.eval(obj, "$..price");
System.out.println(allPrices); // [89.0, 68.0, 1999.0]
// 获取所有叶节点值
List<Object> leaves = (List<Object>) JSONPath.eval(obj, "$..*");
2. 数组切片
// 获取第一本书(索引从0开始)
List<JSONObject> firstBook = (List<JSONObject>) JSONPath.eval(obj, "$.store.book[0:1]");
// 获取所有书籍(跳步取值)
List<JSONObject> oddBooks = (List<JSONObject>) JSONPath.eval(obj, "$.store.book[::2]");
3. 在 Bean 上使用 JSONPath
Fastjson2 支持对 Java 对象直接应用 JSONPath:
public class Store {
private List<Book> book;
private Bicycle bicycle;
}
Store store = JSON.parseObject(jsonStr, Store.class);
String title = (String) JSONPath.eval(store, "$.book[0].title");
System.out.println(title); // Java 编程思想
实用技巧
- 性能优化:创建一次
JSONPath对象可重复使用:
JSONPath path = JSONPath.of("$.store.book[*].title");
List<String> titles = (List<String>) path.eval(obj);
- 错误处理:当路径不存在时,返回
null而非异常:
Object result = JSONPath.eval(obj, "$.nonexistent.path");
System.out.println(result); // null
- 结合 Lambda:快速转换结果:
List<String> cheapTitle = JSONPath.eval(obj, "$.store.book[?(@.price < 70)].title")
.stream()
.map(String.class::cast)
.collect(Collectors.toList());
总结
JSONPath 让 Fastjson2 在处理复杂 JSON 结构时变得优雅高效。掌握 JSONPath 都能让 JSON 数据处理代码量减少 50% 以上。路径语法需要多练习,建议用 JSONPath.eval() 在复杂 JSON 上尝试不同路径组合,很快就能得心应手。
Fastjson2 的 JSONPath 实现还支持更多高级用法,如正则匹配、多条件组合等。

