背景:
- 接口自动化测试实现简单、成本较低、收益较高,越来越受到企业重视
- RESTFul 风格的 API 设计大行其道
- JSON 成为主流的轻量级数据交换格式
痛点
接口关联
数据验证
{"status":1,"msg":"登录成功"}
{"status":1,"code":"10001","data":[{"id":1,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"1","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-05-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":2,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"2","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-06-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":3,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"3","unfinishedInterest":"1.0","unfinishedPrincipal":"100.00","repaymentDate":"2018-07-27 12:24:01","actualRepaymentDate":null,"status":"0"}],"msg":"获取信息成功"}
上面的 JSON 结构嵌套了很多信息,完整的匹配几乎不可能成功。比如其中的 createTime 信息,根据执行接口测试用例的时间每次都不一样。同时这个时间是响应结果中较为次要的信息,在进行接口自动化测试时,是可以选择被忽略的。
解决方案
JsonPath 可以完美解决上面的痛点。通过 JsonPath 可以从多层嵌套的 JSON 中解析出所需要的值。
JsonPath
$.store.book[0].title
$['store']['book'][0]['title']
运算符(Operators)
运算符 |
说明 |
$ |
根元素 |
@ |
当前元素 |
* |
通配符,可以表示任何元素 |
.. |
递归搜索 |
. |
子节点(元素) |
[” (, ”)] |
一个或者多个子节点 |
[ (, )] |
一个或者多个数组下标 |
[start:end] |
数组片段,区间为[start,end) |
[?()] |
过滤器表达式,其中表达式结果必须是 boolean 类型,如可以是比较表达式或者逻辑表达式 |
JsonPath 案例
JSON
{ "lemon": { "teachers": [ { "id": "101", "name": "华华", "addr": "湖南长沙", "age": 25 }, { "id": "102", "name": "韬哥", "age": 28 }, { "id": "103", "name": "Happy", "addr": "广东深圳", "age": 16 }, { "id": "104", "name": "歪歪", "addr": "广东广州", "age": 29 } ], "salesmans": [ { "id": "105", "name": "毛毛", "age": 17 }, { "id": "106", "name": "大树", "age": 27 } ] }, "avg": 25}
JsonPath 例子及说明
JsonPath |
路径说明 |
$.lemon.teachers[*].name |
获取所有老师的的名称 |
$..name |
获取所有人的名称 |
$.lemon.* |
所有的老师和销售 |
$.lemon..age |
所有人的年龄 |
$..age |
所有人的年龄 |
$.lemon.teachers[*].age |
所有老师的年龄 |
$.lemon.teachers[3] |
索引为 3(第 4 个)老师的信息 |
$..teachers[3] |
索引为 3(第 4 个)老师的信息 |
$.lemon.teachers[-2] |
倒数第 2 个老师的信息 |
$..teachers[-2] |
倒数第 2 个老师的信息 |
$..teachers[1,2] |
第 2 到第 3 个老师的信息 |
$..teachers[:2] |
索引 0(包含)到索引 2(不包含)的老师信息 |
$..teachers[1:3] |
索引 1(包含)到索引 3(不包含)的老师信息 |
$..teachers[-2:] |
最后的两个老师的信息 |
$..teachers[2:] |
索引 2 开始的所有老师信息 |
$..teachers[?(@.addr)] |
所有包含地址的老师信息(jsonpath_rw 不支持) |
$.lemon.teachers[?(@.age < 20)] |
所有年龄小于 20 的年龄信息(jsonpath_rw 不支持) |
使用 jsonpath 模块
安装 jsonpath 模块
pip install jsonpath==0.75
解析
# 1:导入相关模块import jsonimport jsonpath# 2: 准备json字符串jsonStr = ''' { "lemon": { "teachers": [ { "id": "101", "name": "华华", "addr": "湖南长沙", "age": 25 }, { "id": "102", "name": "韬哥", "age": 28 }, { "id": "103", "name": "Happy", "addr": "广东深圳", "age": 16 }, { "id": "104", "name": "歪歪", "addr": "广东广州", "age": 29 } ], "salesmans": [ { "id": "105", "name": "毛毛", "age": 17 }, { "id": "106", "name": "大树", "age": 27 } ] }, "avg": 25}'''# 3:加载json字符串为json对象json_obj = json.loads(jsonStr)# 4:使用jsonpath模块的jsonpath方法提取信息# eg1: 提取所有包含addr属性的老师信息,结果为list类型results = jsonpath.jsonpath(json_obj,"$..teachers[?(@.addr)]") print(results)# 输出结果:[{'id': '101', 'name': '华华', 'addr': '湖南长沙', 'age': 25}, {'id': '103', 'name': 'Happy', 'addr': '广东深圳', 'age': 16}, {'id': '104', 'name': '歪歪', 'addr': '广东广州', 'age': 29}]# eg2:提取所有年龄小于20岁的老师的name,结果为list类型results2 = jsonpath.jsonpath(json_obj,"$.lemon.teachers[?(@.age < 20)].name") print(results2)# 输出结果为:['Happy']
使用 jsonpath_rw
安装 jsonpath_rw 模块
pip install jsonpath-rw
解析
# 1:导入相关模块import jsonfrom jsonpath_rw import jsonpath, parse# 2: 准备json字符串jsonStr = ''' # 同上(略)'''# 3:加载为json对象json_obj = json.loads(jsonStr)# 4:采用parse创建jsonpath对象(该案例是得到所有的老师name)jsonpath_expr = parse('$.lemon.teachers[*].name')# 5:通过jsonPath检索json后返回匹配的数据,类型是DatumInContext的listdatumInContexts = jsonpath_expr.find(json_obj)# 采用列表推导式检索出所有匹配的值values = [datum.value for datum in datumInContexts]print(values)# 输出结果为:['华华', '韬哥', 'Happy', '歪歪']# 案例2:提取索引为4的老师的namejsonpath_expr = parse('$.lemon.teachers[3].name')datumInContexts = jsonpath_expr.find(json_obj)print(datumInContexts)values = [datum.value for datum in datumInContexts]print(values)# 结果为:['歪歪']
更多 jsonpath_rw 用法参考:
https://pypi.org/project/jsonpath-rw/
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!