Python requests模块发送JSON字符串而非x-www-form-urlencoded参数字符串

65 投票
3 回答
186657 浏览
提问于 2025-04-30 05:30

我原以为使用x-www-form-urlencoded格式的POST请求应该在请求的主体中发送一个经过URL编码的参数字符串。但是,当我这样做的时候

data = json.dumps({'param1': 'value1', 'param2': 'value2'})
Requests.post(url, data=data)

接收端的请求主体看起来是这样的:

{"param1": "value1", "param2": "value2"}

但我本来期待得到的是这个

param1=value1&param2=value2

我该如何让请求以第二种形式发送数据呢?

暂无标签

3 个回答

13

简短回答和示例:

import requests

the_data = {"aaa": 1, "bbb": 2, "ccc": "yeah"}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
# Execute the post
requests.post("http://bla.bla.example.com", data=the_data, headers=headers)
# You have POSTed this HTTP body: aaa=1&bbb=2&ccc=yeah (note, although the content-type is called urlencoded the data is not in the URL but in the http body)
# to this url: "http://bla.bla.example.com"

Requests库会帮你把JSON格式的数据转换成url编码的字符串。

参考资料:

MDN网页文档Requests库的url编码表单

16

重要的是要说明,这个方法不适用于嵌套的json数据。也就是说,如果你的数据是这样的:

# Wrong
data = {'param1': {'a':[100, 200]},
        'param2': 'value2',
        'param3': False}

# You have to convert values into string:
data = {'param1': json.dumps({'a':[100, 200]}),
        'param2': 'value2',
        'param3': json.dumps(False)}
189

你之所以得到JSON格式的数据,是因为你明确调用了json.dumps来生成一个JSON字符串。只要不这样做,你就不会得到JSON字符串。换句话说,把你的第一行改成这样:

data = {'param1': 'value1', 'param2': 'value2'}

正如文档所解释的,如果你把一个字典作为data的值传入,它会被编码成表单格式;而如果你传入一个字符串,它会原样发送。


举个例子,在一个终端窗口中:

$ nc -kl 8765

在另一个终端窗口中:

$ python3
>>> import requests
>>> d = {'spam': 20, 'eggs': 3}
>>> requests.post("http://localhost:8765", data=d)
^C
>>> import json
>>> j = json.dumps(d)
>>> requests.post("http://localhost:8765", data=j)
^C

在第一个终端中,你会看到第一个请求的内容是这个(并且Content-Type是application/x-www-form-urlencoded):

spam=20&eggs=3

…而第二个请求的内容是这个(没有Content-Type):

{"spam": 20, "eggs": 3}

撰写回答