JsonPath,类似于XPath在XML中的作用。其提供了对Json格式数据的解析能力
操作符
$
查询的根节点,其中根节点可以是数组或对象
.< name > 或 [ ' name ' ]
在JsonPath表达式可以使用点语法、括号语法来访问子节点
..
可进行递归搜索
[ ' name ' (, ' name ' )]
对于括号语法而言,其还支持访问多个子节点
[< index > (, < index >)]
针对数组元素的索引操作符,其中0为起始索引。负数索引表示数组中倒数第几个元素,例如,-1表示倒数第一个元素,-2表示倒数第2个元素
[start:end]
针对数组元素的切片操作符,其表示获取索引在[start,end)区间范围的元素。显然这里是左闭右开区间
特别地,当start省略时,默认为0;当end省略时,则可以获取数组中剩余部分的全部元素。但二者不可同时省略
此外,在切片操作符中同样支持负数索引
*
通配符,在任何需要名称、数字的地方都可以使用
@
用于下文所述过滤器表达式当中,用于指代过滤器当前正在处理的节点对象。其效果类似于Java中的this关键字
[?(< expression >)]
过滤器表达式,表达式结果必须是布尔值。下图即是一个典型的使用过滤器对数组元素进行过滤的示例
其中过滤器支持地操作符,常见地有:
- == :判断是否相等
- != :判断是否不相等
- < :判断是否小于
- <= :判断是否小于等于
- > :判断是否大于
- >= :判断是否大于等于
- =~ :判断左侧 是否 匹配右侧的正则。例如:[? (@.age =~ /\d+/)]
- in :判断左侧 是否 存在于 右侧的集合中。例如:[? (@.size in [ 'S' , 'M' , 'L' ])]
- nin :判断左侧 是否 不存在于 右侧的集合中。例如:[? (@.size nin [ 'S' , 'M' , 'L' ])]
- subsetof :判断左侧 是否为 右侧集合的子集。例如:[? (@.sizes subsetof [ 'S' , 'M' , 'L' ])]
- anyof :判断左侧 是否与 右侧集合 存在交集。例如:[? (@.sizes anyof [ 'S' , 'M' , 'L' ])]
- noneof :判断左侧 是否与 右侧集合 无交集。例如:[? (@.sizes noneof [ 'S' , 'M' , 'L' ])]
- size :判断左侧 数组长度 或 字符串长度 是否为 指定值。例如:[? (@.name size 3)]
此外对于< expression >部分而言,还可以使用逻辑运算符:&&与、||或、!非。以此构建更复杂的表达式
基于Java的实践——Jayway JsonPath
Jayway JsonPath则提供了Java版本的实现,方便开发者进行集成使用。只需引入下述依赖即可
1 | <!--Json Path--> |
为了便于后续行文演示方便,这里准备了一个较为复杂的Json数据
1 | { |
快速入门
Jayway JsonPath 非常方便,开箱即用
1 | public class Demo1 { |
其中,start1的方式适用于仅仅需要读取1次数据;而start2则通过先解析后读取的方式,适用于多次读取的场景。避免start1方式重复解析带来损耗
反序列化
在Jayway JsonPath中提供了多种JsonProvider,其中默认的为JsonSmartJsonProvider。这里我们期望能够直接对读取的数据进行反序列化,这里我们选用JacksonJsonProvider,此时要求jackson-databind依赖的版本至少为2.4.5。故这里我们先添加Jackson依赖
1 | <!--Jackson--> |
Demo如下所示
1 | import com.jayway.jsonpath.Configuration; |
效果如下所示
如果Json中字段在对应类中缺失相应属性,可通过设置Jackson选项来忽略不存在的属性,避免上述代码在反序列失败
1 | import com.fasterxml.jackson.databind.DeserializationFeature; |
过滤器谓词
前面提到JsonPath中支持过滤器表达式,为此在Jayway JsonPath中提供了相应的谓词过滤器。具体地,我们可以使用内联谓词、Filter谓词、自定义谓词3种方式进行实践。其中对于Filter谓词、自定义谓词而言,需要在jsonpath字符串中使用占位符?来代替所传递的过滤器谓词。如果jsonpath字符串中使用多个占位符?,则应按相应顺序传入过滤器谓词参数
1 | import com.jayway.jsonpath.*; |
效果如下所示
修改Json
此外在Jayway JsonPath中还提供了对Json指定字段值的修改能力,假设测试Json如下所示
1 | { |
测试代码如下所示
1 | public class Demo3 { |
符合预期