接口测试 python3 的 request.post () 方法中,传参 data 与 json 的区别

xiaoxiao · 2019年12月20日 · 最后由 t-bug 回复于 2019年12月27日 · 4384 次阅读

python3 的 request.post() 方法的源码:

def post(url, data=None, json=None, **kwargs):
    r"""Sends a POST request.

    :param url: URL for the new :class:`Request` object.
    :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request('post', url, data=data, json=json, **kwargs)

data 和 json 参数既可以是 str,也可以是 dict。它们的区别如下:

  • json 不管是 str 还是 dict,如果不指定 headers 中的 content-type,默认为 application/json
  • data 为 dict 时,如果不指定 headers 中的 content-type,默认为 application/x-www-form-urlencoded,相当于普通 form 表单提交的形式,此时数据可以从 request.post 里面获取,而 request.body 的内容则为 a=1&b=2 的这种形式.注意,即使指定 content-type=application/json,request.body 的值也是类似于 a=1&b=2,所以并不能用 json.loads(request.body.decode()) 得到想要的值
  • data 参数为 str 时,如果不指定 headers 中的 content-type,默认为 application/json

以下测试例子:
1、以【空气质量发布】iOS 端 app 为例,先抓包,启动 app,首页 url 为:http://epapi.moji.com/json/home/homePage, 如图可以看到 request 对应的 headers 和 data 情况:

2、在代码中添加 headers 和 data,完整测试代码如下,它有两种实现方式:

# -*- coding: utf-8 -*-
# @file: test_requests.py.py
# @author: xiaoxiao
# @date  : 2019/12/19

import requests
import json

# 统一的headers
my_headers = {
    'Accept': '*/*',
    'User-Agent': 'AirMonitoring/3.0.6 (iPhone; iOS 11.4.1; Scale/2.00)',
    'Accept-Language': 'zh-Hans-CN;q=1, en-CN;q=0.9, zh-Hant-CN;q=0.8, zh-Hant-HK;q=0.7',
    'Content-Type': 'application/json',
    'Content-Length': '383',
    'Host': 'epapi.moji.com',
    'Accept-Encoding': 'gzip',
    'Connection': 'keep-alive'
}

# 统一的data
my_data = {
    'common': {
        'cityid': '110000',
        'app_version': '45030006',
        'device': 'iPhone9,1',
        'apnsisopen': '0',
        'platform': 'iPhone',
        'uid': 2154359387456724365,
        'language': 'CN',
        'identifier': '95DD96CD-A3BD-48C4-A507-E63FBBDED29C',
        'token': '<545a468e 92bed312 6fe0add2 999d3a52 b9d4422a 867060c2 2d676371 b0ec5ef9>'
    },
    'params': {
        'longitude': '116.2991775173611',
        'cityId': '110000',
        'latitude': '40.05391682942708'
    }
}

# 空气质量发布app的首页请求
top_request = 'http://epapi.moji.com/json/home/homePage'


# @allure.feature('空气质量发布app的首页')
def test_top():
    # 方法1:采用json:dict
    print(type(my_data))
    s = requests.post(top_request, json=my_data)
    print(s)

    # 方法二:通过json.dumps把json:dict转换为data:str
    print(type(json.dumps(my_data)))
    s = requests.post(top_request, headers=my_headers, data=json.dumps(my_data))
    print(s)

    s = json.loads(s.text)
    print('Response:' + str(s))
    assert s['code'] == 0  # 校验接口返回是否正常


if __name__ == '__main__':
    test_top()
    # pytest.main()

最终结果输出:

<class 'dict'>
<Response [200]>
<class 'str'>
<Response [200]>
Response:{'current': {'aqi': 38, 'pm25': 13.0, 'pm10': 38.0, 'o3': 12.0, 'so2': 2.0, 'no2': 48.0, 'co': 0.6, 'nearestStationAqi': 58, 'time': '12/20 09:00', 'aqiLevel': 1, 'maxPollution': '', 'tips': '各类人群可正常活动。', 'tipsLevel': 1, 'condition': '晴', 'temperature': '-4', 'windPowder': '2级', 'humidity': '35', 'today': {'condition': '晴', 'minAqi': 60, 'maxAqi': 80, 'maxPollution': 'NO₂', 'conditionIco': 0, 'tips': '极少数异常敏感人群应减少户外活动。', 'tipsLevel': 2}, 'tomorrow': {'condition': '多云', 'minAqi': 90, 'maxAqi': 110, 'maxPollution': 'PM2.5', 'conditionIco': 1, 'tips': '极少数异常敏感人群应减少户外活动。', 'tipsLevel': 2}}, 'trendList24aqi': {'list': [{'time': '11:00', 'value': '23', 'id': 0}, {'time': '12:00', 'value': '17', 'id': 1}, {'time': '13:00', 'value': '17', 'id': 2}, {'time': '14:00', 'value': '18', 'id': 3}, {'time': '15:00', 'value': '17', 'id': 4}, {'time': '16:00', 'value': '17', 'id': 5}, {'time': '17:00', 'value': '22', 'id': 6}, {'time': '18:00', 'value': '21', 'id': 7}, {'time': '19:00', 'value': '23', 'id': 8}, {'time': '20:00', 'value': '20', 'id': 9}, {'time': '21:00', 'value': '18', 'id': 10}, {'time': '22:00', 'value': '18', 'id': 11}, {'time': '23:00', 'value': '14', 'id': 12}, {'time': '00:00', 'value': '13', 'id': 13}, {'time': '01:00', 'value': '13', 'id': 14}, {'time': '02:00', 'value': '16', 'id': 15}, {'time': '03:00', 'value': '21', 'id': 16}, {'time': '04:00', 'value': '21', 'id': 17}, {'time': '05:00', 'value': '22', 'id': 18}, {'time': '06:00', 'value': '24', 'id': 19}, {'time': '07:00', 'value': '26', 'id': 20}, {'time': '08:00', 'value': '32', 'id': 21}, {'time': '09:00', 'value': '38', 'id': 22}]}, 'forecastWeatherData7': [{'dayTitle': '昨天', 'day': '12/19', 'minAqi': 40, 'maxAqi': 60, 'maxPollution': 'NO₂', 'condition': '晴', 'conditionIco': 0}, {'dayTitle': '今天', 'day': '12/20', 'minAqi': 60, 'maxAqi': 80, 'maxPollution': 'NO₂', 'condition': '晴', 'conditionIco': 0}, {'dayTitle': '明天', 'day': '12/21', 'minAqi': 90, 'maxAqi': 110, 'maxPollution': 'PM2.5', 'condition': '多云', 'conditionIco': 1}, {'dayTitle': '星期日', 'day': '12/22', 'minAqi': 80, 'maxAqi': 95, 'maxPollution': 'PM2.5', 'condition': '晴', 'conditionIco': 0}, {'dayTitle': '星期一', 'day': '12/23', 'minAqi': 70, 'maxAqi': 90, 'maxPollution': 'PM2.5', 'condition': '多云', 'conditionIco': 1}, {'dayTitle': '星期二', 'day': '12/24', 'minAqi': 130, 'maxAqi': 150, 'maxPollution': 'PM2.5', 'condition': '阴', 'conditionIco': 2}, {'dayTitle': '星期三', 'day': '12/25', 'minAqi': 80, 'maxAqi': 100, 'maxPollution': 'PM2.5', 'condition': '晴', 'conditionIco': 0}], 'updateDate': '1576808550094', 'cityCenterLongitude': 116.407112, 'cityCenterLatitude': 39.904138, 'code': 0, 'rc': {'c': 0}}

参考原文链接:https://blog.csdn.net/grace666/article/details/90481970

共收到 12 条回复 时间 点赞

那么,什么时候用 data 什么时候用 json

楼主用的抓包工具是什么呀

萤火虫minu 回复

window 用 fiddler,Mac 用 Charles

married577 回复


如果是这种 form data,就用 data 就行,也可以看 content-type,再决定用哪个😂

我的意思是,在 content-type 里提前指定好,就不用纠结用 data 还是 json 的问题了吧

married577 回复

并不能这样,因为你的 data 是 json 结构,不是纯 dict,是无法请求成功的😂

json 数据那边可以把 json 转字符串。主要看那个接口需求是用啥。。

xiaoxiao 回复

那你的意思是,data 或 json,必须要看入参类型

xiaoxiao 回复

Charles

那是说用 data 时,最好数据类型是 str 么

关于什么时候使用 json,什么时候使用 data,可以自己在电脑上敲一敲代码,领悟一下。
另外,提供一个不错的调试方法:
将 request 发送到http://httpbin.org/post,header 中的设置。然后查看其返回值,可以看到服务器接收到的数据格式以及
简单的调用方法如下:
r = requests.post("http://httpbin.org/post", data=payload)
print(r.text)

详细的情况 requests 的官方文档中应该有。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册