接口测试requests.post方法中data与json参数区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口测试requests.post方法中data与json参数区别相关的知识,希望对你有一定的参考价值。
参考技术A 「这个问题困扰我好久了,我经常分不清,今天刚好趁着这个机会,来总结下。」1.先看一下requests的源码:
「为了一探究竟,我们先看看源码里面怎么说的。」
不要看到英文就发怵,这东西最开始都是老外发明的。不要怕,跟着我一块硬着头皮啃就是了。
源码其实已经说的很明白了。对于data来说我们可以传入Dictionary, list of tuples, bytes, or file-like object ,对于json我们就只能传入json型的数据。
「切记:对于python字典和json虽然长得看起来一样,但是序列化格式还是有区别的。」 很多同学容易搞混淆,这个大家一定要记住。
看完源码,好像是理解了,好像又没有理解。怎么办,去网上找找有没有人详细分析过。
2.来看看我搜索到的答案:
NO.1
「为了加深对该知识点的理解,我也在网上做了一些搜索。」 我感觉说的挺不错的,摘录于此。
这个是通过提交请求的角度来说的,思路挺好。
NO.2
「再来看下面这一条:」
https://blog.csdn.net/liudinglong1989/article/details/104604626
感觉是不是总结的挺好,并且作者还给了验证。但是,说到但是就说明此事有转折哦。
NO.3
「我又搜到了这个:」
https://www.cnblogs.com/yanlin-10/p/9820694.html
「注意一下,上面的两个说法有点冲突。」 而且两者都有举例。这就麻烦了,到底谁说的是对的呢。我们找点权威的资料来看看吧。
3.再回过头来看源码:
「怎么办?对了,还是看源码。」 下面就让我们一点一点来拆解。打开编辑器,一步步切进源码看看。
步骤1
注意,这里用的是pycharm编辑器。
步骤2
步骤3
步骤4
步骤5
步骤6
终于切到能解答我们疑问的地方了。 「你可能会问,你是怎么找到这里的,我也不知道,这个目前也是凭着自己的感觉来找,不一定对,希望读者朋友们保持质疑的态度来看我的文章。」
这里说到,当data是None而Json不为None时,content_type就是application/json类型。后面那个基于各种条件下之后(就是没有json,然后也不满足七七八八的条件),最后会出现content_type = 'application/x-www-form-urlencoded'的情况(这块有点模糊,记录个TODO)。
敲重点喽
至于为什么上面的说法不一致,大概是因为他们都是通过实践发现:当传入的数据为data且data为字符串类型时,在控制台打印的requests.header里content_type='text/plain'。
「我仔细看了,发现他们都是基于Django下做的例子。这样貌似有一定的不合理之处。」 为什么呢? 「因为当我使用requests进行接口操作的时候,我用的是这个库的东西,它自己默认了一套规则。 当你用Django来证明这个结论时,Django框架很可能又结合自己的一套东西默认了一些东西。」 所以我看到上图NO.2的作者特别说明了下:
大概是作者也蒙了,本来想证明呢,突然发现出现了结果和人家requests库里说的不一致的情况,但又无法解释。
通过这一路的分析,我来总结一下。在requests中 「body体里面放入数据,一般要么以json的方式传入,要么是以data的方式传入。 未指定content_type时,以data的方式传入数据content_type = 'application/x-www-form-urlencoded',以json的方式传入数据content_type ='application/json'。」 也就是说上图NO.2的作者是对的,NO.3的作者说法欠妥。 「当然有一点我们要清楚这是requests库这样实现的。」
你会发现我用了很多可能、大概的词语,因为我个人能力,目前还没有能力把Django和requests库研究的很深,我也没法和这些大牛联系问清楚。 「但有一点是清楚的,两者不一致是正常的,并不是完全一样的东西。」
4.再来看下官方文档的举例吧
你看,关于这个问题我也是翻了好多资料,想找找证据。 「前几天特意去读了读官方文档,没有什么特殊的发现。」 也就是在写这篇文章的时候,我突然发现我有点理解了,就这样开窍了,高兴了一小会儿。
「原文链接在此:」
https://docs.python-requests.org/en/master/user/quickstart/#more-complicated-post-requests
5.最后的总结
总而言之,记住这句话:用data参数提交数据时,request.body的内容则为a=1&b=2的这种形式,用json参数提交数据时,request.body的内容则为'"a": 1, "b": 2'的这种形式。
6. 再说说我的想法
当我们在开发测试的时候,其实要传入什么样类型的数据其实已经定好了,不会有那么多纠结的。 「之所以我会有这样的疑惑,也是因为对自己的不自信,既然源码里已经说了,为什么还不敢果断的下结论,我还需要修炼哦,加油!」
7.其它的收获
「当我们传入数据的时候,可以使用不同的content_type,根据自己的需求即可。」 这是我在写这篇文章的时候学到的,链接放这里,回头忘记的时候多来看看。
https://zhuanlan.zhihu.com/p/202978890
https://imququ.com/post/four-ways-to-post-data-in-http.html
> 借鉴自:我去吹吹风 https://www.mdnice.com/writing/75b1900ec1824ba6ad3a5851a3bd876f
python接口自动化测试-requests.post()
上一节介绍了 requests.get() 方法的基本使用,本节介绍 requests.post() 方法的使用:
本文目录:
一、方法定义
二、post方法简单使用
1、带数据的post
2、带header的post
3、带json的post
4、带参数的post
5、普通文件上传
6、定制化文件上传
7、多文件上传
一、方法定义:
1、到官方文档去了下requests.post()方法的定义,如下:
2、源码:
3、常用返回信息:
二、post方法简单使用:
1、带数据的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) data = {‘key1‘:‘value1‘,‘key2‘:‘value2‘} r = requests.post(url,data=data) #response = r.json() print (r.text)
输出:
{ "args": {}, "data": "", "files": {}, "form": { "key1": "value1", "key2": "value2" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
2、带header的post:
# -*- coding:utf-8 -*- import requests import json
host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) headers = {"User-Agent":"test request headers"} # r = requests.post(url) r = requests.post(url,headers=headers) #response = r.json()
输出:
{ "args": {}, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "test request headers" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
3、带json的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post"
url = ‘‘.join([host,endpoint]) data = { "sites": [ { "name":"test" , "url":"www.test.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"weibo" , "url":"www.weibo.com" } ] } r = requests.post(url,json=data) # r = requests.post(url,data=json.dumps(data)) response = r.json()
输出:
{ "args": {}, "data": "{\\"sites\\": [{\\"url\\": \\"www.test.com\\", \\"name\\": \\"test\\"}, {\\"url\\": \\"www.google.com\\", \\"name\\": \\"google\\"}, {\\"url\\": \\"www.weibo.com\\", \\"name\\": \\"weibo\\"}]}", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "140", "Content-Type": "application/json", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": { "sites": [ { "name": "test", "url": "www.test.com" }, { "name": "google", "url": "www.google.com" }, { "name": "weibo", "url": "www.weibo.com" } ] }, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
4、带参数的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) params = {‘key1‘:‘params1‘,‘key2‘:‘params2‘} # r = requests.post(url) r = requests.post(url,params=params) #response = r.json() print (r.text)
输出:
{ "args": { "key1": "params1", "key2": "params2" }, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post?key2=params2&key1=params1" }
5、普通文件上传:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post"
url = ‘‘.join([host,endpoint]) #普通上传 files = { ‘file‘:open(‘test.txt‘,‘rb‘) } r = requests.post(url,files=files) print (r.text)
输出:
{ "args": {}, "data": "", "files": { "file": "hello world!\\n" }, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "157", "Content-Type": "multipart/form-data; boundary=392865f79bf6431f8a53c9d56c62571e", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
6、定制化文件上传:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) #自定义文件名,文件类型、请求头 files = { ‘file‘:(‘test.png‘,open(‘test.png‘,‘rb‘),‘image/png‘) } r = requests.post(url,files=files) print (r.text)heman793
输出比较在,就不帖了。
7、多文件上传:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) #多文件上传 files = [ (‘file1‘,(‘test.txt‘,open(‘test.txt‘, ‘rb‘))), (‘file2‘, (‘test.png‘, open(‘test.png‘, ‘rb‘))) ] r = requests.post(url,files=files) print (r.text)
输出上,太多内容,不帖了。
8、流式上传:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ‘‘.join([host,endpoint]) #流式上传 with open( ‘test.txt‘ ) as f: r = requests.post(url,data = f) print (r.text)
输出:
{ "args": {}, "data": "hello world!\\n", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "13", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
以上是关于接口测试requests.post方法中data与json参数区别的主要内容,如果未能解决你的问题,请参考以下文章