本文最后更新于:2021年6月15日 晚上
前言
在工作中,经常会遇到从一串 JSON 中提取一个或多个字段的情况,常用的做法就是将其反序列化为 JSONObject 对象,然后从对象中获取,如果是 JSONArray 就进行迭代获取,总之比较麻烦。可以使用 JsonPath 快速提取所需信息。
JSONPATH 简明语法
JsonPath |
描述 |
$ |
根节点 |
@ |
当前节点 |
.or[] |
子节点 |
.. |
选择所有符合条件的节点 |
* |
所有节点 |
[] |
迭代器标示,如数组下标 |
[,] |
支持迭代器中做多选 |
[start:end:step] |
数组切片运算符 |
?() |
支持过滤操作 |
() |
支持表达式计算 |
尝试 JsonPath 前提准备
maven 工程引入 jsonpath 的依赖
| <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.4.0</version> </dependency>
|
有人说,FastJson 自带了 JSONPath,为什么不用要用这个呢?我只能回 FastJson 确实很好用,但是 FastJson 的 JsonPath 是真难用!
JsonPath 简单入门版
给定一串 JSON 如下所示:
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
| { "store": { "book": [ { "category": "文学", "author": "曹雪芹", "title": "红楼梦", "price": 47.20 }, { "category": "心理", "author": "凯利·麦格尼格尔", "title": "自控力", "price": 30.20 }, { "category": "励志", "author": "史蒂芬·柯维", "title": "高效能人士的七个习惯", "isbn": "7515326395", "price": 51 }, { "category": "小说", "author": "毛姆", "title": "月亮与六便士", "isbn": "7533936027", "price": 19.50 } ], "bicycle": { "color": "red", "price": 19.95 } } }
|
需要按照条件提取信息
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 class JsonPathExample { public static void main(String[] args) throws IOException { File file = new File(JsonPathExample.class.getClassLoader().getResource("store.json").getPath()); String storeJson = FileUtils.readFileToString(file); println(JsonPath.read(storeJson, "$.store.book[0].author").toString());
println(JsonPath.read(storeJson, "$.store.book[*].author").toString());
println(JsonPath.read(storeJson, "$.store.book[?(@.category =='文学')]").toString());
println(JsonPath.read(storeJson, "$.store.book[?(@.price > 50)]").toString());
println(JsonPath.read(storeJson, "$.store.book[?(@.isbn)]").toString());
println(JsonPath.read(storeJson, "$..price").toString()); }
private static void println(String str) { System.out.println(str); } }
|
以上基本上,简单提取需要 JSON 中的信息便已经足够了,以下为扩展内容,也是我在工作中使用到的。
JsonPath 复杂结构版
给定一串 JSON 如下所示
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
| { "bookId": 7333, "volumeDetailList": [ { "title": "卷一 恢弘世界", "volumeId": 28585, "chapterDetailList": [ { "chapterId": 11719110, "free": true, "name": "第1章 上九天", "price": 0, "words": 1678, "contentId": 2930434 }, { "chapterId": 1719111, "free": true, "name": "第2章:揽月", "price": 0, "words": 2390, "contentId": 2930444 } ] }, { "title": "卷二 在人家", "volumeId": 285852, "chapterDetailList": [ { "chapterId": 1719120, "free": false, "name": "第3章:千年后之始", "price": 19, "words": 2989, "contentId": 29540933 }, { "chapterId": 17133111, "free": false, "name": "第4章:破冰而生", "price": 30, "words": 3409, "contentId": 29540988 } ] } ] }
|
读取需要的相关信息
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
| public class JsonPathExample2 { public static void main(String[] args) throws IOException { File file = new File(JsonPathExample2.class.getClassLoader().getResource("chapterlist.json").getPath()); String chapterlistJson = FileUtils.readFileToString(file);
println(JsonPath.read(chapterlistJson, "$..title").toString());
println(JsonPath.read(chapterlistJson, "$..name").toString());
println(JsonPath.read(chapterlistJson, "$.volumeDetailList[*].chapterDetailList[?(@.chapterId == '17133111')].contentId").toString()); println(JsonPath.read(chapterlistJson, "$..[?(@.chapterId == '17133111')].contentId").toString()); }
private static void println(String str) { System.out.println(str); } }
|
常用JsonPath在线解析工具网站
这两个网站都可以在线写 JsonPath 语句,可以用来校验写的是否正确而不用去跑代码程序,比较方便
参考文章
小结
在工作中使用到的时候,也不熟悉 JsonPath 的语法,写出了比较复杂的 JsonPath,但是在写这篇博客的时候,又写了一般,发现了有很多自己写的 JsonPath 语句是可以精简的,比如倒数第二条 JsonPath 语句可以精简为它下面那句。
在输出的时候,可以发现自己认知中不足之处,写博客还是能给自己带来很多好处的,希望自己能够笔耕不息~