FastJson 解析神器JsonPath 使用手册

在这里插入图片描述

一、快速入门

1.1 Json Path 介绍

  正如XPath对XML的解析一样,JSONPath的定义是基于fastjson的json路径解析,对JSON文档的一种解析工具。通过JSONPath可以轻松的对JSON文档获取指定“路径”的数据,在非常复杂的json结构中,对于一些获取和判断操作,不需要层层的去get,可以通过简洁的JsonPath表达式精准找到需要的部分。

1.2 引入依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>x.y.z</version>
</dependency>
  • JSONPath在线验证:https://www.jsonpath.cn/

二、基本使用

2.1 基本用法

根据需要解析的路径,使用JsonPath类的静态方法read解析json字符串,并使用read方法返回的Object进行数据获取

String jsonStr = "{'store':{'book':[" +
    "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
    "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
    "'bicycle':{'color':'red','price':19.95}}}\n";
System.out.println("所有author节点:" + JSONPath.read(jsonStr, "$..author"));

如果是json格式的字符串,则先解析为JSONObject,然后就能直接使用JSONPath.eval了。

String jsonStr = "{'store':{'book':[" +
    "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
    "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
    "'bicycle':{'color':'red','price':19.95}}}\n";
// 先解析JSON数据  
JSONObject jsonObject = JSON.parseObject(jsonStr);
System.out.println("\n Book数目:" + JSONPath.eval(jsonObject, "$.store.book.size()"));
System.out.println("第一本书title:" + JSONPath.eval(jsonObject, "$.store.book[0].title"));
System.out.println("price大于10元的book:" + JSONPath.eval(jsonObject, "$.store.book[price > 10]"));
System.out.println("price大于10元的title:" + JSONPath.eval(jsonObject, "$.store.book[price > 10][0].title"));
System.out.println("bicycle的所有属性值" + JSONPath.eval(jsonObject, "$.store.bicycle.*"));
System.out.println("bicycle的color和price属性值" + JSONPath.eval(jsonObject, "$.store.bicycle['color','price']"));

2.2 基本语法

Json Path的语法相对简单,它采用开发语言友好的表达式形式,如下所示。

JSONPath描述
$文档的根对象,所有路径表达式的开始
@文档当前节点对象,类似于java 中的 this 字段
.子节点,例如$.name
[num]数组访问,其余num 是数字,可以是负数。例如$[0].leader.departments[-1].name
[‘key’]属性访问。例如$[‘name’]
[‘key0’,‘key1’]多个属性访问。例如$[‘id’,‘name’]
[num0,num1,num2]数组多个元素访问,其余num 是数字,可以是负数,返回数组中的多个元素。
例如$[0,1,-2,5]
可以理解为递归搜索,递归匹配所有子元素。例如$…name
*通配符,适用于任何地方,例如$.leader.*
[start:end]数组范围访问,其中start、end 是开始、结束的下标,可以是负数,返回数组中的多个元素。
[?(expression)]过滤器表达式,必须返回一个布尔值,例如$.departs[?(name)]
()脚本表达式
String jsonStr = "{'store':{'book':[" +
    "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
    "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
    "'bicycle':{'color':'red','price':19.95}}}\n";
System.out.println("根节点:" + JSONPath.read(jsonStr, "$"));
System.out.println("根节点下的store节点:" + JSONPath.read(jsonStr, "$.store"));
System.out.println("store节点下的所有子节点:" + JSONPath.read(jsonStr, "$.store.*"));
System.out.println("第一个book节点:" + JSONPath.read(jsonStr, "$.store..book[0]"));
JSONPath语义
$根对象
$[-1]最后元素
$[:-2]第1个至倒数第2个
$[1:]第2个之后所有元素
$[1,2,3]集合中1、2、3个元素

2.3 函数语法

可以在JsonPath表达式执行后进行调用,其输入值为表达式的结果。

函数描述输出类型
min()数字数组的最小值Double
max()数字数组的最大值Double
avg()数字数组的平均值Double
stddev()数字数组的标准方差Double
length()返回数组的长度Integer
sum()数字数组求和Double
keys()没搞明白这个函数是做什么的Set
concat(X)将数组中元素拼接成一个新的元素
append(X)添加新元素到输出数组中
String jsonStr = "{'store':{'book':[" +
        "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
        "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
        "'bicycle':{'color':'red','price':19.95}}}\n";
System.out.println("第一个book节点的价格,并向下取整:" + JSONPath.read(jsonStr, "$.store.book[0].price.floor()"));

2.4 筛选语法

  筛选语法用于筛选满足特定条件的节点,是用于过滤数组的逻辑表达式,一个通常的表达式形如:[?(@.age > 18)],可以通过逻辑表达式&&或||组合多个过滤器表达式,例如[?(@.price < 10 && @.category == ‘fiction’)],字符串必须用单引号包围,例如[?(@.color == ‘blue’)]。

操作符描述
==字符串类型对象属性比较过滤。例如$.departs[name = ‘123’],比较操作符支持=、!=、>、>=、<、<=
>数值类型对象属性比较过滤,例如$.departs[id >= 123],比较操作符支持=、!=、>、>=、<、<=
=~判断是否符合正则表达式
like字符串类型 like 过滤,例如$.departs[name like ‘sz*’],通配符只支持%,也支持 not like
rlike字符串类型正则匹配过滤,例如departs[name like ‘aa(.)*’],正则语法为jdk的正则语法,支持not rlike
inIN 过滤,支持字符串、数值类型。例如:
$.departs[name in (‘wenshao’,‘Yako’)]
$.departs[id not in (101,102)]
nin排除
betweenBETWEEN过滤, 支持数值类型,支持not between。例如:
$.departs[id between 101 and 201]
$.departs[id not between 101 and 201]
empty左边数组或字符串为空
size左边数组或字符串大小和右边匹配
String jsonStr = "{'store':{'book':[" +
        "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
        "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
        "'bicycle':{'color':'red','price':19.95}}}\n";
System.out.println("选取store节点下,价格小于10的book节点:" + JSONPath.read(jsonStr, "$.store.book[?(@.price < 10)]"));
System.out.println("选取store节点下,价格小于10的book节点:" + JSONPath.eval(jsonStr, "$.store.book[?(@.price < 10)]"));

三、高级用法

JsonPath支持许多高级用法,如动态筛选、多条件筛选、嵌套查询等。

3.1 动态筛选

JsonPath支持使用Java代码动态生成筛选条件。

String jsonStr = "{'store':{'book':[" +
        "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
        "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
        "'bicycle':{'color':'red','price':19.95}}}\n";
//定义筛选条件
String filter = "$.store.book[?(@.price < %s)].price";

//动态生成筛选条件,获取价格小于10的book节点的价格
Object result = JSONPath.read(jsonStr, String.format(filter, 10));
System.out.println(result.toString());

3.2 多条件筛选

JsonPath支持同时使用多个条件进行筛选。

String jsonStr = "{'store':{'book':[" +
        "{'category':'reference','author':'Nigel Rees','title':'Sayings of the Century','price':8.95}," +
        "{'category':'fiction','author':'Evelyn Waugh','title':'Sword of Honour','price':12.99}]," +
        "'bicycle':{'color':'red','price':19.95}}}\n";
//定义筛选条件
String filter = "$.store.book[?(@.price < %s && @.author == '%s')].title";

//动态生成筛选条件,获取价格小于10且作者是Nigel Rees的book节点的书名
Object result = JSONPath.read(jsonStr, String.format(filter, 10, "Nigel Rees"));
System.out.println(result.toString());

3.3 嵌套查询

JsonPath支持在筛选条件中使用嵌套查询。


四、API

4.1 示例

{
    "store":{
        "book":[
            {
                "category":"reference",
                "author":"Nigel Rees",
                "title":"Sayings of the Century",
                "price":8.95
            },
            {
                "category":"fiction",
                "author":"Evelyn Waugh",
                "title":"Sword of Honour",
                "price":12.99
            },
            {
                "category":"fiction",
                "author":"Herman Melville",
                "title":"Moby Dick",
                "isbn":"0-553-21311-3",
                "price":8.99
            },
            {
                "category":"fiction",
                "author":"J. R. R. Tolkien",
                "title":"The Lord of the Rings",
                "isbn":"0-395-19395-8",
                "price":22.99
            }
        ],
        "bicycle":{
            "color":"red",
            "price":19.95
        }
    },
    "expensive":10
}
JsonPath表达式结果
$.store.book[*].author获取json中store下book下的所有author值
$…author获取所有的 author 的值
$.store.book.*获取json中store下book下的所有值
$.store…price获取json中store下所有price的值
$…book[2]获取json中book数组的第3个值
$…book[-2]倒数的第二本书
$…book[0,1]前两本书
$…book[:2]从索引0(包括)到索引2(排除)的所有图书
$…book[1:2]从索引1(包括)到索引2(排除)的所有图书
$…book[-2:]获取json中book数组的最后两个值
$…book[2:]获取json中book数组的第3个到最后一个的区间值
$…book[?(@.title)]获取json中book数组中包含title的所有节点
$.store.book[?(@.price < 10)]获取json中book数组中price<10的所有值
$…book[?(@.price <= $[‘expensive’])]获取json中book数组中price<=$[‘expensive’]结果的所有值
*$…book[?(@.author =~ /.REES/i)]获取json中book数组中的作者以REES结尾的所有值(REES不区分大小写)
$…*逐层列出json中的所有值,层级由外到内
$…book.length()获取json中book数组的长度

2.2 常用方法

使用Fastjson中的JSONPath解析器,可以调用 JSONPath.read 方法,获取指定的字符串。

List<String> authors = JsonPath.read(JSON_DATA, "$.store.book[*].author");

如果需要多次读,那么这种方法不够理想,因为每次都会重新解析一次json数据

  可以看到,在这段难以阅读的json字符串中,我们轻松取到了 author 的值。这只是read方法的用法,下面介绍一下这个类其他的几个关键方法的作用:

public class JSONPath {
    // 求值,静态方法
	public static Object eval(Object rootObject, String path);
    // 计算Size,Map非空元素个数,对象非空元素个数,Collection的Size,数组的长度。其他无法求值返回-1
    public static int size(Object rootObject, String path);
    // 是否包含path中是否存在对象
    public static boolean contains(Object rootObject, String path);
    // 是否包含path中是否存在指定值,如果是集合或者数组,在集合中查找value是否存在 
    public static boolean containsValue(Object rootObject, String path, Object value);
    // 修改制定路径的值,如果修改成功,返回true,否则返回false
    public static boolean set(Object rootObject, String path, Object value);
    // 在数组或者集合中添加元素。添加成功返回 true,失败返回 false
    public static boolean arrayAdd(Object rootObject, String path, Object… values);
    // 删除指定path的元素, 删除成功返回 true,失败返回 false
    public static boolean remove(Object root, String path);
    // 编译一个jsonpath为对象
    public static JSONPath compile(String path);
    // 从一个json字符串中, 根据指定的path读取为Json对象
    public static Object read(String json, String path);
    // 返回指定Java对象的属性的所有json访问path
    public static Map<String, Object> paths(Object javaObject);
}

2.3 类型转换

  在java中使用JsonPath时,当我们知道我们读取过后的返回值是什么类型时,JsonPath会尝试将其转换为我们想要的类型,如下所示:

String author = (String) JSONPath.read(JSON_DATA, "$.store.book[0].author");
System.out.println(author);

四、小结

  使用JSONPath类提供的静态方法能够非常快速地对json字符串进行路径解析,将指定位置的json字符串以对象的形式返回,方便了系统的调用者。JSONPath与XPath的路径解析规则差不多,熟练使用这种解析方式,再用上Fastjson提供的静态方法,可以将在需要使用JSONPath的项目中将解析速度大大提升。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独泪了无痕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值