JsonPath是一种简单的方法来提取给定JSON文档的部分内容。JsonPath有许多编程语言,如Javascript,Python和PHP,Java。
参考地址:https://github.com/json-path/JsonPath
JsonPath提供的json解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的json内容。如果可以使用JsonPath来解析json,以下的问题可以被解决:
2.1数据不使用特殊的脚本,可以在客户端交互的发现并取并获取。
2.2客户机请求的JSON数据可以减少到服务器上的相关部分,这样可以最大限度地减少服务器响应的带宽使用率。
符号 | 描述 |
---|---|
$ | 查询的根节点对象,用于表示一个json数据,可以是数组或对象 |
@ | 过滤器断言(filter predicate)处理的当前节点对象,类似于java中的this字段 |
* | 通配符,可以表示一个名字或数字 |
… | 可以理解为递归搜索,Deep scan. Available anywhere a name is required. |
. |
表示一个子节点 |
[‘ |
表示一个或多个子节点 |
[ |
表示一个或多个数组下标 |
[start:end] | 数组片段,区间为[start,end),不包含end |
[?( |
过滤器表达式,表达式结果必须是boolean |
可以在路径的尾部调用,函数的输出是路径表达式的输出,该函数的输出是由函数本身所决定的。
函数 | 描述 | 输出 |
---|---|---|
min() | 提供数字数组的最小值 | Double |
max() | 提供数字数组的最大值 | Double |
avg() | 提供数字数组的平均值 | Double |
stddev() | 提供数字数组的标准偏差值 | Double |
length() | 提供数组的长度 | Integer |
过滤器是用于筛选数组的逻辑表达式。一个典型的过滤器将是[?(@.age > 18)],其中@表示正在处理的当前项目。 可以使用逻辑运算符&&和||创建更复杂的过滤器。 字符串文字必须用单引号或双引号括起来([?(@.color == ‘blue’)] 或者 [?(@.color == “blue”)])。
操作符 | 描述 |
---|---|
== | left等于right(注意1不等于’1’) |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
=~ | 匹配正则表达式[?(@.name =~ /foo.*?/i)] |
in | 左边存在于右边 [?(@.size in [‘S’, ‘M’])] |
nin | 左边不存在于右边 |
size | (数组或字符串)长度 |
empty | (数组或字符串)为空 |
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.5.0</version>
</dependency>
{
"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,
"author": "test"
}
},
"expensive": 10
}
/**
* 需要解析的json串
*/
String json = "....";
/**
* 读取json,这样的弊端就是每次都读取json,如果仅使用一次可以这样,多次使用不推荐
* $.store.book[*].author 获取store下的book中author属性的值
* "$..author" 获取store中author属性的值
*/
List<String> authorsBook = JsonPath.read(json, "$.store.book[*].author");
List<String> authorsAll = JsonPath.read(json, "$..author");
System.out.println("authorsBook = " + authorsBook);
//结果:authorsBook = ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
System.out.println("authorsAll = " + authorsAll);
//结果:authorsAll = ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien", "test"]
如果仅解析一次可以直接用上面的方法,否则用一下面
/**
* 需要解析的json串
*/
String json = "....";
/**
* 获取需要解析的json多次处理
*/
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
String author0 = JsonPath.read(document, "$.store.book[0].author");
System.out.println("author0 = " + author0);
//结果:author0 = Nigel Rees
String author1 = JsonPath.read(document, "$.store.book[1].author");
System.out.println("author1 = " + author1);
//结果:author1 = Evelyn Waugh
返回值可以为List、对象及时间类型等
String testJson = "{\"date_as_long\" : 1411455611975}";
/**
* 返回值类型是时间对象
* 结果:date = Tue Sep 23 15:00:11 CST 2014
*/
Date date = JsonPath.parse(testJson).read("$['date_as_long']", Date.class);
System.out.println("date = " + date);
/**
* 返回类型为实体对象
* "$.store.book[0]" 获取store的book中的第一个
* 结果:book = {category='reference', author='Nigel Rees', title='Sayings of the Century', price=8}
*/
Book book = JsonPath.parse(json).read("$.store.book[0]",Book.class);
System.out.println("book = " + book);
/**
* 返回类型为List
* "$.store.book[*].author" 获取store的book中author属性值
* 结果:typeList = ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
*/
List<String> typeList = ctx.read("$.store.book[*].author");
System.out.println("typeList = " + typeList);
创建断言有三种方式
/**
* 断言,大白话就是通过表达式筛选出自己想要的数据
* "$.store.book[?(@.price > 10)]" 从store的book筛选出price大于10
* 结果: [{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},
* {"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]
*/
List<Map<String, Object>> expensiveBooks = JsonPath.parse(json)
.read("$.store.book[?(@.price > 10)]");
System.out.println("expensiveBooks = " + expensiveBooks);
注意占位符? 为路径中的过滤器。 当提供多个过滤器时,它们按照占位符数量与提供的过滤器数量相匹配的顺序应用。 您可以在一个过滤器操作[?,?]中指定多个谓词占位符,这两个谓词都必须匹配。
/**
* 过滤器器断言
* filter(where("category").is("fiction").and("price").lte(10D) 过滤出category=fiction并且price<=10
*/
Filter one = filter(
where("category").is("fiction").and("price").lte(10D)
);
Filter two = filter(
where("category").is("fiction").and("price").lte(8D)
);
/**
* 结果:result1 = [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]
*/
List<Map<String, Object>> result1 =
JsonPath.parse(json).read("$.store.book[?]", one);
System.out.println("result1 = " + result1);
/**
* 结果:result2 = []
*/
List<Map<String, Object>> result2 =
JsonPath.parse(json).read("$.store.book[?,?]", one,two);
System.out.println("result2 = " + result2);
自定义断言。
/**
* 自定义断言
* "$.store.book[?].isbn" 查找store的book中isbn的属性值
* 结果:books = ["0-553-21311-3","0-395-19395-8"]
*/
Predicate booksWithISBN = new Predicate() {
@Override
public boolean apply(PredicateContext ctx) {
return ctx.item(Map.class).containsKey("isbn");
}
};
List<Map<String, Object>> books =
JsonPath.parse(json).read("$.store.book[?].isbn", List.class, booksWithISBN);
System.out.println("books = " + books);
/**
* 改变json中的某个属性值
*/
String newJson = JsonPath.parse(json).set("$['store']['book'][0]['author']", "Paul").jsonString();
System.out.println("newJson = " + newJson);
DEFAULT_PATH_LEAF_TO_NULL:此选项使JsonPath对于缺少的叶子返回null
ALWAYS_RETURN_LIST:此选项配置JsonPath返回列表
ALWAYS_RETURN_LIST:如果选项ALWAYS_RETURN_LIST存在,将返回一个空列表
ALWAYS_RETURN_LIST:如果选项ALWAYS_RETURN_LIST不存在返回null
String testJsonConfig = "[\n" +
" {\n" +
" \"name\" : \"john\",\n" +
" \"gender\" : \"male\"\n" +
" },\n" +
" {\n" +
" \"name\" : \"ben\"\n" +
" }\n" +
"]";
Configuration conf = Configuration.defaultConfiguration();
//结果:gender0 = male
//String gender0 = JsonPath.using(conf).parse(testJsonConfig).read("$[0]['gender']");
//System.out.println("gender0 = " + gender0);
//结果:抛PathNotFoundException
//String gender1 = JsonPath.using(conf).parse(testJsonConfig).read("$[1]['gender']");
//System.out.println("gender1 = " + gender1);
Configuration conf2 = conf.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
//结果:gender0 = male
String gender0 = JsonPath.using(conf2).parse(testJsonConfig).read("$[0]['gender']");
System.out.println("gender0 = " + gender0);
//结果:gender1 = null
String gender1 = JsonPath.using(conf2).parse(testJsonConfig).read("$[1]['gender']");
System.out.println("gender1 = " + gender1);
//The first two books:获取json中book数组的第1和第2两个个值
List<Object> authors6 = JsonPath.read(json, "$..book[0,1]");
//All books from index 0 (inclusive) until index 2 (exclusive):获取json中book数组的前两个区间值
List<Object> authors7 = JsonPath.read(json, "$..book[:2]");
//All books from index 1 (inclusive) until index 2 (exclusive):获取json中book数组的第2个值
List<Object> authors8 = JsonPath.read(json, "$..book[1:2]");
//Last two books:获取json中book数组的最后两个值
List<Object> authors9 = JsonPath.read(json, "$..book[-2:]");
//Book number two from tail:获取json中book数组的第3个到最后一个的区间值
List<Object> authors10 = JsonPath.read(json, "$..book[2:]");
//All books in store that are not "expensive":获取json中book数组中price<=expensive的所有值
List<Object> authors13 = JsonPath.read(json, "$..book[?(@.price <= $['expensive'])]");
//All books matching regex (ignore case):获取json中book数组中的作者以REES结尾的所有值(REES不区分大小写)
List<Object> authors14 = JsonPath.read(json, "$..book[?(@.author =~ /.*REES/i)]");
//The number of books:获取json中book数组的长度
List<Object> authors16 = JsonPath.read(json, "$..book.length()");