Python 填坑之——requests.post 方法中 data 参数与 json 参数区别
近期在使用 WxPusher 推送服务,官方文档要求,在发送 POST 请求时应当将数据放入 body 内,并设置 Content-Type 为 application/json。
本人多次使用 data 参数进行请求,均以失败告终。后来换用 json 参数,即刻成功,特此分享记录。
预备知识
Http 协议介绍
HTTP/1.1
协议规定,一个完整的 HTTP
请求分为三个部分:请求行,请求头和请求主体。大概框架如下:
1 | <method> <request-URL> <version> |
例如:
1 | POST http://test.com HTTP/1.1 |
Content-Type 字段介绍
application/x-www-form-urlencoded
这是原生 form
表单,是最常见的编码方式,用途广泛。当
Content-Type
字段被设置为
application/x-www-form-urlencoded
时,body
数据为 key/value
的形式,通过 URL 编码后使用
&
符号进行连接。大部分的服务端都可以支持这种编码方式。
前文中的“示例”采用的就是这种编码方式。
application/json
随着 JSON
规范的流行,这种编码方式被越来越多人采用,原因是这种编码方式可以直接提交结构化的数据,方便数据的处理。
例如:
1 | POST http://test.com HTTP/1.1 |
仔细观察,不难发现,上述两种编码方式最大的不同就体现在
<body>
部分。
前者的提交类似于 Python 中的 str
类型,而后者则是
dict
类型。
而 requests
库在进行 POST
请求时,如果使用的是 data=
参数,则默认使用
application/x-www-form-urlencoded
编码方式;如果使用
json=
参数,则默认使用 application/json
编码方式。
案例分析
相信看完前文,一大部分小伙伴就已经找到了问题所在,下面结合本次我掉进的“坑”再来分析下。
本次调用 WxPusher
时,我使用了如下代码:
1 | import requests |
为了满足官方的需求,我特意手动设置了 headers
中的
Content-Type
为 application/json
。
但是,当我使用 data=
参数时,requests
库默认使用 application/x-www-form-urlencoded
方式对我的数据进行编码。
此时,虽然 headers
中的 Content-Type
仍然是
application/json
,但我所提交的数据就已经不是
json
格式的了,而是前文所述的类似于 str
的文本,导致服务器无法解析数据,从而出错。
The End
希望上述分享能对大家有所帮助,以免再次掉进“两种不同的参数造成数据传输格式不同”的“坑”里。
参考链接: requests 中 post 参数 data 和 json 区别