FastJson 解析神器JsonPath 使用手册

文章目录

  • 一、快速入门
    • 1.1 Json Path 介绍
    • 1.2 引入依赖
  • 二、基本使用
    • 2.1 基本用法
    • 2.2 基本语法
    • 2.3 函数语法
    • 2.4 筛选语法
  • 三、高级用法
    • 3.1 动态筛选
    • 3.2 多条件筛选
    • 3.3 嵌套查询
  • 四、API
    • 4.1 示例
    • 2.2 常用方法
    • 2.3 类型转换
  • 四、小结

一、快速入门

1.1 Json Path 介绍

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

1.2 引入依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>x.y.zversion>
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
in IN 过滤,支持字符串、数值类型。例如:
$.departs[name in (‘wenshao’,‘Yako’)]
$.departs[id not in (101,102)]
nin 排除
between BETWEEN过滤, 支持数值类型,支持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的项目中将解析速度大大提升。

你可能感兴趣的:(开发工具,Java,技术栈,数据库,前端)