我们在做接口测试的时候,返回的json结构比较复杂,特别是嵌套比较多的时候,就不太好处理。有没有比较简便的方法呢?
肯定是有的,python里面有jsonpath,jsonpath-rw等模块来快速处理json结构。这两个模块差不多,讲讲其中的jsonpath吧。
JsonPath模块
1、JsonPath介绍
用来解析多层嵌套的json数据;JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript, Python, PHP 和 Java。
2、JsonPath 对于 JSON 来说,相当于 XPath 对于 XML。
安装方法:pip install jsonpath
官方文档:http://goessner.net/articles/JsonPath
3、JsonPath与XPath语法对比:
Json结构清晰,可读性高,复杂度低,非常容易匹配,下表中对应了XPath的用法。
背景:
1、接口自动化测试实现简单、成本较低、收益较高,越来越受到企业重视。
2、restful风格的api设计大行其道。
3、json成为主流的轻量级数据交换格式。
痛点:
1、接口关联也称为关联参数。在应用业务接口中,完成一个业务功能时,有时候一个接口可能不满足业务的整个流程逻辑,需要多个接口配合使用。简单的案例如:B接口的成功调用依赖于A接口,需要在A接口的响应数据(response)中拿到需要的字段,在调用B接口的时候,传递给B接口作为B接口请求参数,拿到后续响应的响应数据。接口关联通常可以使用正则表达式去提取需要的数据,但对于json这种简洁、清晰层次结构、轻量级的数据交互格式。使用正则未免有点杀鸡用牛刀的感觉(是的,因为我不擅长写正则表达式),我们需要更加简单、直接的提取json数据的方式。
2、数据验证,这里的数据验证指的是对响应结果进行数据的校验,接口自动化测试中,对于简单的响应结果(json),可以直接和期望结果进行比对,判断是否完全相等即可。如 json {“status”:1,“msg”:“登录成功”}
对于格式较复杂,尤其部分数据存在不确定性、会根据实际情况变化的响应结果,简单的判断是否完全相等(断言)通常会失败。
3、解决方案
JsonPath可以完美解决上面的痛点。通过JsonPath可以从多层嵌套的Json中解析出所需要的值。
- JsonPath参照XPath解析xml的方式来解析Json
- JsonPath用符号$表示最外层对象,类似于Xpath中的根元素
- JsonPath可以通过点语法来检索数据,如:
shell $.store.book[0].title
也可以使用中括号[]的形式,如shell $[‘store’][‘book’][0][‘title’]
例如:
d={
"error_code": 0,
"stu_info": [
{
"id": 2059,
"name": "小红",
"sex": "女",
"age": 21,
"addr": "上海浦东大道32号",
"grade": "天蝎座",
"phone": "18378309272",
"gold": 10896,
"info":{
"card":434345432,
"bank_name":'中国银行'
}
},
{
"id": 2067,
"name": "小亮",
"sex": "男",
"age": 28,
"addr": "上海南京西路1088号",
"grade": "天蝎座",
"phone": "12345678915",
"gold": 100
}
]
}
res= d["stu_info"][1]['name'] #取某个学生姓名的原始方法:通过查找字典中的key以及list方法中的下标索引
print(res) #输出结果是:小亮
import jsonpath
res1=jsonpath.jsonpath(d,'$..name') #嵌套n层也能取到所有学生姓名信息,$表示最外层的{},..表示模糊匹配
print(res1) #输出结果是list:['小红', '小亮']
res2= jsonpath.jsonpath(d,'$..bank_name')
print(res2) #输出结果是list:['中国银行']
res3=jsonpath.jsonpath(d,'$..name123') #当传入不存在的key(name)时,返回False
print(res3) #输出结果是:False
再来一个例子:
dict = { "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
}
}
}
import jsonpath
res1=jsonpath.jsonpath(dict,'$..author')
print(res1)
ok, 我们可以尝试来做接口:
对36氪的快讯接口解析,只要知道最终要取的字段名就好,不用写完整的字典取值,可以省不少事:
import requests
import json
import jsonpath
header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
url = 'https://36kr.com/api/newsflash?&per_page=20'
response = requests.get(url,
headers=header,
timeout=5
)
dict = json.loads(response.text)
title=jsonpath.jsonpath(dict,"$..title]")
des=jsonpath.jsonpath(dict, '$..description')
publish=jsonpath.jsonpath(dict, '$..published_at')
for i in range(20):
print(title[i]," ",des[i], " ", publish[i])
最后: 可以在公众号:伤心的辣条 ! 自行领取一份216页软件测试工程师面试宝典文档资料【免费的】。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
学习技术千万不要孤军奋战,最好是能抱团取暖,相互成就一起成长,群众效应的效果是非常强大的,大家一起学习,一起打卡,会更有学习动力,也更能坚持下去。你可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)
喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
好文推荐
转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!