JSONPath解析JSON数据结构

fastjson的JSONPath是一种查询和导航JSON文档的路径表达式语言,用于从JSON数据结构中提取和筛选数据。对于复杂的json数据结构,在进行获取和判断操作时,不需层层的去get,可以通过简洁的JsonPath表达式精准找到需要的部分。

官方地址:https://github.com/alibaba/fastjson/wiki/JSONPath

依赖项

xml 复制代码
<!-- JSONObject -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

样例数据

java 复制代码
String jsonStr =
        "{'store':" +
            "{'book':[" +
                "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
                "{'category':'reference','author':'陈渠珍(ChenQuzhen)','title':'艽野尘梦','price':10.95}," +
                "{'category':'reference','author':'','title':'刀戟戡魔录','price':10.95}," +
                "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
            "'bicycle':{'color':'red','price':19.95}" +
            "}" +
        "}";
JSONObject jsonObject = JSON.parseObject(jsonStr);

根据需要解析的路径,使用JsonPath类的静态方法read() 解析json字符串。如果是json格式的字符串,则先解析为JSONObject,然后就能直接使用JSONPath.eval()方法了,样例如下:

一、基本语法

JSONPath 描述
$ 文档的根对象
@ 文档当前节点对象,类似于java 中的 this 字段
. 当前节点的子节点,如 $.name
num 数组访问,num是数字,可以是负数。如 $0.leader.departments-1.name
num0,num1,num2 数组多个元素访问,num 是数字,可以是负数,返回数组中的多个元素。如 $0,1,-2,5
start:end 数组范围访问,start、end 是开始、结束的下标,可以是负数,返回数组中的多个元素。
'key' 属性访问。如 $'name'
'key0','key1' 多个属性访问。如 $'id','name'
.. 可以理解为递归搜索,递归匹配所有子元素。如 $..name
* 通配符,取所有value集合,如$.leader.*

利用上述基本语法可以提取JSON结构中的特定数据,样例如下:

java 复制代码
/*
 * JSONPath.eval(jsonStr, "$.") 提取对应节点的数据
 * JSONPath.remove(jsonStr, "$.") 删除对应的节点数据 
 * JSONPath.set(jsonStr, "$.userInfo.addData", "sinder") 插入指定的值,甚至可以直接操作json中的数组或者对象数据。
 */
JSONObject jsonRoot  = (JSONObject) JSONPath.read(jsonStr, "$");
JSONObject jsonStore = (JSONObject) JSONPath.read(jsonStr, "$.store");
Collection<JSONObject> jsonStoreVals = (Collection<JSONObject>) JSONPath.read(jsonStr, "$.store.*");
JSONObject jsonBook0 = (JSONObject) JSONPath.read(jsonStr, "$.store..book[0]");
List<String> authors = (List<String>)JSONPath.read(jsonStr, "$..author");
System.out.println("根节点:" + jsonRoot);
System.out.println("根节点下的store节点:" + jsonStore);
System.out.println("store节点的所有value集合:" + jsonStoreVals);
System.out.println("store节点下的首个book节点:" + jsonBook0); // {"author":"Nigel Rees","price":8.95,"category":"reference","title":"Sayings of the Century"}
System.out.println("根节点下的所有author的value集合:" + authors); // [Nigel Rees, 陈渠珍(ChenQuzheng), Evelyn Waugh]

Collection<Object> bicycleVals = (Collection<Object>) JSONPath.eval(jsonObject, "$.store.bicycle.*");
Collection<Object> bicycleVals2 = (Collection<Object>)JSONPath.eval(jsonObject, "$.store.bicycle['color','price']");
List<String> bookAuthors = (List<String>) JSONPath.read(jsonStr, "$.store.book[*].author");
System.out.println("bicycle节点的所有value集合:" + bicycleVals);
System.out.println("bicycle节点的color和price的value集合:" + bicycleVals2);
System.out.println("book节点的author属性值:" + bookAuthors); // ["Nigel Rees","陈渠珍(ChenQuzheng)","Evelyn Waugh"]

Integer size = (Integer)JSONPath.eval(jsonObject, "$.store.book.size()");
String title = (String)JSONPath.eval(jsonObject, "$.store.book[0].title");
System.out.println("book数量:" + size);
System.out.println("第一本书title:" + title);

二、函数语法

java 复制代码
System.out.println("首个book节点的价格,并向下取整:" + JSONPath.read(jsonStr, "$.store.book[0].price.floor()"));
System.out.println("book节点price的个数:" + JSONPath.read(jsonStr, "$.store.book['price'].length()"));
System.out.println("book节点price的最小值:" + JSONPath.read(jsonStr, "$.store.book['price'].min()"));
System.out.println("book节点price的最大值:" + JSONPath.read(jsonStr, "$.store.book['price'].max()"));
//        System.out.println("book节点price的平均值:" + JSONPath.read(jsonStr, "$.store.book['price'].avg()"));
//        System.out.println("book节点price的标准差:" + JSONPath.read(jsonStr, "$.store.book['price'].stddev()"));
//        System.out.println("book节点price的平均值:" + JSONPath.read(jsonStr, "$.store.book['price'].sum()"));

三、筛选语法

JSONPath 描述
?(expression) 过滤器表达式,必须返回一个布尔值,如 $.departs?(@.name != null \&\& @.name != '')

筛选语法是用于过滤数组的逻辑表达式,如:?(@.price \> 10)。可以使用 &&、|| 组合多个过滤器表达式,如:?(@.price \< 10 \&\& @.category == 'reference'),其中,字符串常量必须用单引号包围。筛选语法支持的符号如下:

1、== != > >= < <= 数值和字符串的比较

java 复制代码
JSONArray ja1 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.price < 10 && @.category == 'reference')]");
JSONArray ja2 = (JSONArray) JSONPath.eval(jsonStr, "$.store.book[?(@.price < 10 && @.category == 'reference')]");
System.out.println("筛选store节点下price小于10的book节点:" + ja1);
System.out.println("筛选store节点下price小于10的book节点:" + ja2);

String firstBookTitle = (String)JSONPath.eval(jsonObject, "$.store.book[price > 10][0].title");
System.out.println("筛选store节点下price大于10元的title(第一本):" + firstBookTitle);

2、between查询数值范围内,not between查询数值范围外 TODO 不支持 !!!

java 复制代码
/// JSONArray between = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.price between 10 and 12)]");
/// System.out.println("between查询数值范围内:" + between);

3、in查询数值范围内,nin查询数值范围外 TODO 只对字符串友好 !!!

java 复制代码
JSONArray in = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.category in ('fiction'))]");
JSONArray nin = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.category nin ('fiction'))]");
System.out.println("in查询字符串范围内:" + in);
System.out.println("nin查询字符串范围外:" + nin);

4、字符串非空

java 复制代码
JSONArray ja7 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.author != null && @.author != '')]");
System.out.println("有作者的书:" + ja7);

5、like 'xxx%'字符串模糊查询, not like '%'字符串模糊查询,

java 复制代码
JSONArray ja3 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.author like '陈%')]");
JSONArray ja4 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.author not like '陈%')]");
System.out.println("陈氏作者写的书:" + ja3);
System.out.println("其他作者写的书:" + ja4);

6、rlike 'xxx'字符串正则匹配,not rlike 'xxx'字符串正则排除

java 复制代码
JSONArray ja5 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.author rlike '[\\w\\s]+')]");
JSONArray ja6 = (JSONArray) JSONPath.read(jsonStr, "$.store.book[?(@.author not rlike '[\\w\\s]+')]");
System.out.println("英文作者写的书(正则匹配):" + ja5);
System.out.println("其他作者写的书(正则排除):" + ja6);
相关推荐
jun_bai4 小时前
使用java安全的移动文件
java
caishenzhibiao4 小时前
市场同步系统 同花顺期货通指标
java·c语言·c#
Devin~Y4 小时前
从本地生活电商到 AI RAG:互联网大厂 Java 面试场景完整实战
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
520拼好饭被践踏4 小时前
JAVA+Agent学习day25
java·开发语言·学习
大黄说说4 小时前
Java 并发大坑:volatile、synchronized、Lock 三者如何选择?
java·开发语言
红叶舞4 小时前
成数据绑定对象,在应用程序中处理完数据后,将更新的数据序列化为JSON传回远端服务器,很多移动应用使用了这种模式处理服务器端的数据。 ...
运维·服务器·json
IMPYLH4 小时前
HTML 的 <em> 元素
java·前端·html
啊真真真4 小时前
ArgoCD:我的GitOps探索之旅与未来展望
java·算法·argocd
深入云栈4 小时前
从零手写连接池:Redisson ConnectionsHolder设计与简化实现
java·架构
学编程就要猛5 小时前
解析博客系统后端实现
java·mysql·jwt·摘要算法·加盐