Python Requests包中data和json参数的区别
在Python的Requests库中,data
和json
这两个参数有什么区别呢?
从官方文档上看,似乎没有说得很清楚。
比如这段代码:
import requests
import json
d = {'a': 1}
response = requests.post(url, data=json.dumps(d))
( 注意我们在这里把dict
转换成了JSON哦 ☝️! )
...和这段代码:
import requests
import json
d = {'a': 1}
response = requests.post(url, json=d)
有什么不同吗?
后者会不会自动把Content-Type
这个HTTP头设置为application/json
呢?
3 个回答
根据我的经验,建议使用 json
字段来传递字典,而不是把字典放在 data
字段里。
再次强调,这只是我的经验,我并没有深入研究代码,但看起来 requests 库在处理 json 数据时比单纯使用 json.dumps
更聪明。当我在 data
字段使用 json.dumps
时,遇到过几次服务器(FastAPI)返回“值不是有效的字典”的错误。改用 json
字段后,这些问题就解决了。
补充:今天我看了一下代码。如果你使用 json
参数,requests 库似乎只是设置了 Content-Type
并进行了一些处理:
from .compat import json as complexjson
content_type = 'application/json'
body = complexjson.dumps(json)
if not isinstance(body, bytes):
body = body.encode('utf-8')
在 requests.compat
中,json
只是:
try:
import simplejson as json
except ImportError:
import json
... 所以我真的搞不懂为什么手动使用 data
参数有时候就会失败。¯\_(ツ)_/¯
截至2021年12月,关于使用data
和json
的区别,requests
的文档已经非常清楚了。
(我们对此做了一点小贡献 - 我的PR和你们的点赞证明这曾经是个问题。谢谢大家!)
附言
这并没有直接回答提问者的问题,但如果第一段代码稍微不同一些:
import requests
import json
d = {'a': 1}
response = requests.post(url, data=d)
(注意这里的dict
d
并没有被转换成JSON字符串!)
如果第二段代码保持不变(为了完整性复制一下):
import requests
import json
d = {'a': 1}
response = requests.post(url, json=d)
...那么结果会有很大不同。
第一段代码会生成一个请求,内容类型设置为application/x-www-form-urlencoded
,数据格式是这样的:"a=1"
而第二段代码会生成一个请求,内容类型设置为application/json
,数据格式实际上是这样的:{"a": 1}
- 这是一个JSON字符串。
为了回答我自己的问题,看来我上面给出的两个例子其实是做同样的事情。而且使用 json
参数确实会把请求头中的 content-type
设置为 application/json
。在我上面第一个例子中使用 data
参数时,content-type
就需要手动设置了。