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);
相关推荐
电商API&Tina9 小时前
【电商API接口】开发者一站式电商API接入说明
大数据·数据库·人工智能·云计算·json
m0_672703319 小时前
上机练习第51天
数据结构·c++·算法
左左右右左右摇晃10 小时前
Java并发——synchronized锁
java·开发语言
仰泳的熊猫10 小时前
题目2577:蓝桥杯2020年第十一届省赛真题-走方格
数据结构·c++·算法·蓝桥杯
消失的旧时光-194310 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
灰色小旋风10 小时前
力扣13 罗马数字转整数
数据结构·c++·算法·leetcode
sxlishaobin10 小时前
Java I/O 模型详解:BIO、NIO、AIO
java·开发语言·nio
彭于晏Yan10 小时前
Spring AI(二):入门使用
java·spring boot·spring·ai
有一个好名字11 小时前
vibe codeing 开发流程
java
兑生11 小时前
【灵神题单·贪心】3745. 三元素表达式的最大值 | 排序贪心 | Java
java·开发语言