Java使用JSONPath解析JSON完整内容详解

简介

  JsonPath是一种简单的方法来提取JSON文档的方法。它支持的编程语言有很多,如java、python、JavaScript和PHP。

  JsonPath提供的json解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的json内容。

maven依赖

<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>

操作符

操作符说明
$表示根元素
@当前元素
. or []子元素
n/a父元素
*通配符,表示所有的元素
..选择所有符合条件的节点
[]迭代器标识,如数组下标
[,]连接操作符在XPath 结果合并其它结点集合。JSONP允许name或者数组索引。
[start,step]数组切片操作
?()过滤表达式
()支持表达式计算

函数

函数可以在路径的尾部调用,函数的输出是路径表达式的输出,该函数的输出是由函数本身所决定的

函数描述输出
min()提供数组的最小值Double
max()提供数组的最大值Double
avg()提供数组的平均值Double
stddev()提供数组的标准偏差值Double
length()提供数组的长度Integer
sum()提供数组的总和Double
keys()提供属性键(终端波浪号的替代方案 ~)Set<E>
concat(X)提供带有新项目的路径输出的串联版本like input
append(X)向 json 路径输出数组添加一个项目like input

过滤操作符

过滤器是用于过滤数组的逻辑表达式。 典型的过滤器是 [?(@.age > 18)] ,其中 @ 代表正在处理的当前项目。 可以使用逻辑运算符 && 和 || 来创建更复杂的过滤器。 字符串文字必须用单引号或双引号括起来([?(@.color == 'blue')] 或 [?(@.color == "blue")])。

操作符说明
==left等于right(注意1不等于'1')
!=不等于  
<小于
<=小于等于
>大于
>=大于等于
=~匹配正则表达式[?(@.name =~ /foo.*?/i)]
in左边存在于右边 [?(@.size in [‘S', ‘M'])]
nin左边不存在于右边
subsetof左边是 右边 [?(@.sizes subnetof ['S', 'M', 'L'])] 的子集
anyof左边与右边有交集 [?(@.sizes anyof ['M', 'L'])]
noneof左边与右边没有交集 [?(@.sizes noneof ['M', 'L'])]
size(数组或字符串)长度
empty(数组或字符串)为空

测试的json数据

{
    "text" : "张三",
    "expensive" : 6,
    "body" : {
        "rvNoNum" : 23,
        "rvNoRecords" : [
            {
                "score" : 4,
                "rvAddress" : "2",
                "consignments" : null
            },
            {
                "score" : 8,
                "rvAddress" : "3",
                "consignments" : null
            }
        ]
    }
}

测试代码

package jsonpathdemo;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.JsonPath;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

public class jsonpathTest {

    public static void main(String[] args) throws IOException {

        // 定义需要测试的json字符串
        String testJson = "{\n" +
                "  \"text\": \"张三\",\n" +
                "  \"expensive\": 6,\n" +
                "  \"body\": {\n" +
                "    \"rvNoNum\": 23,\n" +
                "    \"rvNoRecords\": [{\n" +
                "      \"score\": 4,\n" +
                "      \"rvAddress\": \"2\",\n" +
                "      \"consignments\": null\n" +
                "    }, {\n" +
                "      \"score\": 8,\n" +
                "      \"rvAddress\": \"3\",\n" +
                "      \"consignments\": null\n" +
                "    }]\n" +
                "  }\n" +
                "}";

        //使用jackson对字符串反序列化为json对象
        ObjectMapper mapper = new ObjectMapper ( );
        HashMap responseJson = mapper.readValue ( testJson, HashMap.class );


        // 输出text的值
        String text = JsonPath.read(responseJson,"$.text");
        System.out.println (text );

        // 输出rvNoNum的值
        int rvNoNum = JsonPath.read(responseJson,"$.body.rvNoNum");
        System.out.println ( rvNoNum);

        //输出rvNoRecords数组的第2个值
        List<Object> rvNoRecords = JsonPath.read(responseJson,"$..rvNoRecords[1]");
        System.out.println ( rvNoRecords);

        //输出rvNoRecords数组的第1和第2个值
        List<Object> rvNoRecords1 = JsonPath.read(responseJson,"$..rvNoRecords[0,1]");
        System.out.println (rvNoRecords1 );

        //输出rvNoRecords数组中score<=expensive的所有值
        List<Object> rvNoRecords2 = JsonPath.read(responseJson,"$..rvNoRecords[?(@.score < $['expensive'])]");
        System.out.println ( rvNoRecords2);

        //输出rvNoRecords[0]的rvAddress值
        String rvAddress1 = JsonPath.read(responseJson, "$.body.rvNoRecords[0].rvAddress");
        System.out.println ( rvAddress1);

        //输出全部rvAddress的值,使用Iterator迭代
        List<String> rvAddress = JsonPath.read(responseJson,"$.body.rvNoRecords[*].rvAddress");
        System.out.println ( rvAddress);

        //输出rvNoRecords[*]中rvAddress== '2'的rvNoRecords
        List<Object> rvAddress2 = JsonPath.read(responseJson,"$.body.rvNoRecords[?(@.rvAddress == 2)]");
        System.out.println (rvAddress2 );

        //输出rvNoRecords[*]中score>5 的rvNoRecords
        List<Object> score = JsonPath.read(responseJson,"$.body.rvNoRecords[?(@.score>5)]");
        System.out.println ( score);

        //输出rvNoRecords[*]中含有consignments元素的rvNoRecords
        List<Double> consignments = JsonPath.read(responseJson,"$.body.rvNoRecords[?(@.consignments)]");
        System.out.println ( consignments);

        //输出该json中所有rvAddress的值
        List<Object> rvNoNum2 = JsonPath.read(responseJson,"$..rvAddress");
        System.out.println (rvNoNum2 );

        //输出rvNoRecords数组的长度
        Integer length = JsonPath.read(responseJson,"$..rvNoRecords.length()");
        System.out.println (length );

        //可以提前编辑一个路径,并多次使用它
        JsonPath path = JsonPath.compile("$.body.rvNoRecords[*]");
        List<Object> rvNoRecords3 = path.read(responseJson);
        System.out.println (rvNoRecords3 );

    }
}

测试结果:

张三
23
[{"score":8,"rvAddress":"3","consignments":null}]
[{"score":4,"rvAddress":"2","consignments":null},{"score":8,"rvAddress":"3","consignments":null}]
[{"score":4,"rvAddress":"2","consignments":null}]
2
["2","3"]
[{"score":4,"rvAddress":"2","consignments":null}]
[{"score":8,"rvAddress":"3","consignments":null}]
[{"score":4,"rvAddress":"2","consignments":null},{"score":8,"rvAddress":"3","consignments":null}]
["2","3"]
2
[{"score":4,"rvAddress":"2","consignments":null},{"score":8,"rvAddress":"3","consignments":null}]