> 文档中心 > 继 Gson、Jackson、FastJson 之后基于JsonPath解析JSON

继 Gson、Jackson、FastJson 之后基于JsonPath解析JSON

基于JsonPath解析JSON

    • 一、JsonPath 说明
    • 二、JsonPath 语法
      • 1. 常用操作符
      • 2. 常用过滤器操作符
      • 3. 常用函数
    • 三、Java 语言实现JsonPath示例
      • 1. 引入 maven 坐标
      • 2. 数据准备
      • 3. json解析示例
    • 四、JsonPath 其他功能

一、JsonPath 说明

JsonPath是一种用于读取JSON文档的JavaDSL,能够方便快捷的解析复杂逻辑的Json。GitHub:JsonPath ,当然也可以 在线使用。

二、JsonPath 语法

1. 常用操作符

Operator Description
$ 要查询的根元素。表示所有表达式的开始路径
@ 用在筛选器,表示当前节点
* 作为通配符,匹配所有成员
.. 子递归通配符,匹配成员的所有子元素
. .孩子节点名称
['' (, '')] 括号中标注的一个或多个孩子节点
[ (, )] 括号中标注一个或多个孩子节点的下标(索引),从0开始
[start:end] 表示从start下标开始到 end下标结束(不包括 end 下标)孩子节点
[?()] 过滤表达式。表达式的计算结果必须为布尔值

2. 常用过滤器操作符

Operator Description
== 左侧等于右侧。但是 1 不等于 ‘1’
!= 左侧不等于右侧
< 左侧小于右侧
<= 左侧小于等于右侧
> 左侧大于右侧
>= 左侧大于等于右侧
=~ 左侧正则匹配右侧
in 左侧存在于右侧集合
nin 左侧不存在于右侧集合
size 左侧(数组或字符串)的大小应与右侧匹配
empty 左侧(数组或字符串)应为空
subsetof 左侧是右侧的子集。测试时发现无法调通
anyof 左侧与右侧的交集。测试时发现无法调通
noneof 左侧和右侧不相交的部分。测试时发现无法调通

3. 常用函数

Function Description Output type
min() 返回数组的最小值 Double
max() 返回数组的最大值 Double
avg() 返回数组的平均值 Double
stddev() 返回数组的标准方差 Double
length() 返回数组的长度 Integer
sum() 返回数组的总和 Double
keys() 没搞明白这个函数是做什么的 Set
concat(X) 将数组中元素拼接成一个新的元素 like input
append(X) 在 json 上添加元素。测试发现没有作用,提示没有该函数 like input

三、Java 语言实现JsonPath示例

1. 引入 maven 坐标

    com.jayway.jsonpath    json-path    2.7.0

2. 数据准备

添加json文件 /json/ExampleJson.json ,内容如下所示:

{  "store": [    {      "name": "京东",      "label": "like",      "book": [ {   "category": "Java",   "author": "凯·S·霍斯特曼",   "title": "Java核心技术",   "price": 149,   "nation": "M" }, {   "category": "Java",   "author": "Bruce Eckel",   "title": "Java编程思想",   "price": 54.13,   "nation": "M" }, {   "category": "Java",   "author": "方腾飞",   "title": "Java并发编程的艺术",   "price": 48.12,   "nation": "C" }, {   "category": "C++",   "author": "安东尼威廉姆斯",   "title": "C++并发编程实战",   "price": 137.00,   "nation": "M" }, {   "category": "",   "author": "未知",   "title": "测试",   "price": 0,   "nation": "C" }      ],      "bicycle": { "color": "red", "price": 1999.99      },      "avg": 60    },    {      "name": "天猫",      "book": [ {   "category": "Python",   "author": "埃里克·马瑟斯 ",   "title": "Python从入门到实践",   "price": 107,   "nation": "M" }, {   "category": "Python",   "author": "明日科技",   "title": "Python从入门到精通",   "price": 36.80,   "nation": "C" }      ]    }  ],  "from": "互联网"}

3. json解析示例

package com.study;import com.jayway.jsonpath.JsonPath;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.BeforeEach;import org.junit.jupiter.api.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.io.InputStream;/ * @author ouyangrongtao * @since 2022-04-20 22:28 */class JsonPathExampleTest {    private InputStream resource;    private static final Logger LOGGER = LoggerFactory.getLogger(JsonPathExampleTest.class);    @BeforeEach    void setUp() { resource = JsonPathExample.class.getResourceAsStream("/json/ExampleJson.json");    }    @Test    void getAllBookListList() throws IOException { Object books = JsonPath.read(resource, "$..book"); LOGGER.info("获取全部 book 节点:{}", books); Assertions.assertNotNull(books);    }    @Test    void getAllBookList() throws IOException { Object books = JsonPath.read(resource, "$..book[*]"); LOGGER.info("获取全部 book 节点:{}", books); Assertions.assertNotNull(books);    }    @Test    void getAllAuthors() throws IOException { Object authors = JsonPath.read(resource, "$..author"); LOGGER.info("获取全部 book 的 author:{}", authors); Assertions.assertNotNull(authors);    }    @Test    void getJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0]"); LOGGER.info("获取京东store:{}", o); Assertions.assertNotNull(o);    }    @Test    void getBicycleFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].bicycle"); LOGGER.info("获取京东 store 下的 bicycle:{}", o); Assertions.assertNotNull(o);    }    @Test    void getFirstBookFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].book[0]"); LOGGER.info("获取京东 store 下的第一的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getLastBookFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].book[-1]"); LOGGER.info("获取京东 store 下的最后的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getFirstBookOfAuthorFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].book[0]['author', 'title']"); LOGGER.info("获取京东 store 下的第一的 book 的 author 和 title:{}", o); Assertions.assertNotNull(o);    }    @Test    void getFirstAndThirdBookOfAuthorFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].book[0, 2]"); LOGGER.info("获取京东 store 下的第一和第三的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getFirstToThirdBookOfAuthorFromJingdong() throws IOException { Object o = JsonPath.read(resource, "$.store[0].book[0:3]"); LOGGER.info("获取京东 store 下的第一到第三的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getExistLabel() throws IOException { Object o = JsonPath.read(resource, "$.store[?(@.label)]"); LOGGER.info("获取 store 下存在 label 的 store:{}", o); Assertions.assertNotNull(o);    }    @Test    void getNameEqual() throws IOException { Object o = JsonPath.read(resource, "$.store[?(@.name=='京东')]"); LOGGER.info("获取 name=京东 的 store:{}", o); Assertions.assertNotNull(o);    }    @Test    void getPriceGT100() throws IOException { Object o = JsonPath.read(resource, "$..book[?(@.price > 100)]"); LOGGER.info("获取 price 大于 100 的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getPriceGTAvg() throws IOException { Object o = JsonPath.read(resource, "$..book[?(@.price > $.store[0].avg)]"); LOGGER.info("获取 price 大于 avg 的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getCategoryEmpty() throws IOException { Object o = JsonPath.read(resource, "$..book[?(@.category == '')]"); LOGGER.info("获取 Java 和 Python 的 book:{}", o); Assertions.assertNotNull(o);    }    @Test    void getJavaAndPython() throws IOException { Object o = JsonPath.read(resource, "$..book[?(@.category in ['Java', 'Python'])]"); LOGGER.info("获取 Java 和 Python 的 book:{}", o); Assertions.assertNotNull(o);    } @Test    void getMaxPrice() throws IOException { Object o = JsonPath.read(resource, "max($..book[?(@.price)].price)"); LOGGER.info("获取 book 中最高的 price:{}", o); Assertions.assertNotNull(o);    } @Test    void getConcatPrice1() throws IOException { Object o = JsonPath.read(resource, "concat($..book[?(@.price)].price)"); LOGGER.info("获取 book 中的price并拼接起来:{}", o); Assertions.assertEquals(o, "14954.1348.12137.0010736.8");    }    @Test    void getConcatPrice2() throws IOException { Object o = JsonPath.read(resource, "$..book[?(@.price)].price.concat()"); LOGGER.info("获取 book 中的price并拼接起来:{}", o); Assertions.assertEquals(o, "14954.1348.12137.0010736.8");    }}

四、JsonPath 其他功能

  1. 设置指定路径的json值

    @Testvoid setValue() {    String newJson = JsonPath.parse(resource).set("$.from", "oy").jsonString();    LOGGER.info("设置后的新json:{}", newJson);    Assertions.assertNotNull(newJson);}

    注意: 设置值的 path 必须存在,否则报 PathNotFoundException 异常。

  2. 支持缓存,支持自定义
    com.jayway.jsonpath.spi.cache.LRUCache (default, thread safe)
    com.jayway.jsonpath.spi.cache.NOOPCache (no cache)
    自定义缓存使用 CacheProvider.setCache()

  3. JsonProvider SPI
    JsonSmartJsonProvider (default)
    JacksonJsonProvider
    JacksonJsonNodeJsonProvider
    GsonJsonProvider
    JsonOrgJsonProvider
    JakartaJsonProvider