最近团队开发了一个平台,功能界面类似postman
,用例都还是单接口的用例,就是可以绑定一个用户的登录状态和一些常量。验证功能主要分为两类:1、系统验证(包括请求异常、HTTP 状态码、通用响应结构验证);2、功能验证(包括业务 code、文本内容等)。都是通过字符串解析和正则匹配来完成的。
接下来的二期有一个目标就是丰富验证功能和多用例串联起来,这里了解到了一个jsonpath
的工具,经过简单尝试,效果非常理想。因为每一个用例都对应这一个请求,执行完都会返回一个JSonobject
的对象(这里是框架封装好的)。如果使用JSonpath
的标记语言能够完成json
信息的提取,那么就可以完美解决这个需求。
下面分享一下官方的API
的实践。
引入 jar 包
compile group: 'com.jayway.jsonpath', name: 'json-path', version: '2.4.0'
json 数据
首先看官方给的json
数据的Demo
(我做了一点点修改):
JSONObject json = JSON.parseObject("{" +
" \"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" +
" }" +
" }," +
" \"expensive\": 10," +
" \"ss\": [32,32,4,23]" +
"}");
jsonpath
的两种写法
JsonPath
表达式始终以与XPath
表达式与XML
文档结合使用的方式解析JSON
结构数据。JsonPath
中的根对象或者数组用$表示。
JsonPath
表达式可以使用点符号
$.store.book[0].title
或括号符号
$['store']['book'][0]['title']
API
基本的是一个read()
方法:
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param json a json object
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(Object json, String jsonPath, Predicate... filters) {
return parse(json).read(jsonPath, filters);
}
- 对于测试来讲,只需要两个参数即可,足够满足所有使用场景了,而且后面的参数对象对于
fastjson
兼容性不咋好,部分高级语法不支持这个。
获取所有图书的作者列表
jsonpath
:$.store.book[*].author
代码:
Object read = JsonPath.read(json, "$.store.book[*].author");
output(read);
这里可以完全自定义返回对象类型,jsonpath
会自动帮用户完成对象转换,跟下面的这个写法是完全等效的。
List read = JsonPath.read(json, "$.store.book[*].author");
output(read);
输出:
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.6
INFO-> ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
可以看到得到了无论使用object
或者list
得到的结果都是一样的,但是如果使用的不当的对象类型,就会报下面的错误:
Exception in thread "main" java.lang.ClassCastException: net.minidev.json.JSONArray cannot be cast to java.lang.String
at com.fun.ztest.groovy.JsonPathTest.main(JsonPathTest.java:50)
获取所有作者
JSonpath
:$..author
$.store..price
代码省略,输出:
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.6
INFO-> ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.6
INFO-> [19.95,8.95,12.99,8.99,22.99]
可以看到可以不指定具体的key
也可以获取固定层级的某个key
的value
。
获取节点下所有信息
-
JSonpath
:$.store.*
-
JSonpath
:$.ss.*
代码省略,输出:
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.6
INFO-> [{"color":"red","price":19.95},[{"author":"Nigel Rees","price":8.95,"category":"reference","title":"Sayings of the Century"},{"author":"Evelyn Waugh","price":12.99,"category":"fiction","title":"Sword of Honour"},{"author":"Herman Melville","price":8.99,"isbn":"0-553-21311-3","category":"fiction","title":"Moby Dick"},{"author":"J. R. R. Tolkien","price":22.99,"isbn":"0-395-19395-8","category":"fiction","title":"The Lord of the Rings"}]]
INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.6
INFO-> [32,32,4,23]
下期讲讲如果处理json
数组,欢迎继续关注!
- 公众号FunTester首发,更多原创文章:FunTester430+ 原创文章,欢迎关注、交流,禁止第三方擅自转载。