文章目录

一、快速入门1.1 Json Path 介绍1.2 引入依赖

二、基本使用2.1 基本用法2.2 基本语法2.3 函数语法2.4 筛选语法

三、高级用法3.1 动态筛选3.2 多条件筛选3.3 嵌套查询

四、API4.1 示例2.2 常用方法2.3 类型转换

四、小结

一、快速入门

1.1 Json Path 介绍

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

1.2 引入依赖

com.alibaba

fastjson

x.y.z

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()数字数组的最小值Doublemax()数字数组的最大值Doubleavg()数字数组的平均值Doublestddev()数字数组的标准方差Doublelength()返回数组的长度Integersum()数字数组求和Doublekeys()没搞明白这个函数是做什么的Setconcat(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 likerlike字符串类型正则匹配过滤,例如departs[name like ‘aa(.)*’],正则语法为jdk的正则语法,支持not rlikeinIN 过滤,支持字符串、数值类型。例如: $.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 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 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的项目中将解析速度大大提升。

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。