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 { |
符合预期