如何以 JSON 格式发送 POST 请求?
Posted
技术标签:
【中文标题】如何以 JSON 格式发送 POST 请求?【英文标题】:How do I send a POST request as a JSON? 【发布时间】:2012-04-02 12:42:33 【问题描述】:data =
'ids': [12, 3, 4, 5, 6 , ...]
urllib2.urlopen("http://abc.com/api/posts/create",urllib.urlencode(data))
我想发送一个 POST 请求,但其中一个字段应该是数字列表。我怎样才能做到这一点 ? (JSON?)
【问题讨论】:
那不是已经是数字列表了吗? 如果不知道 API 期望什么样的输入,就无法回答这个问题。 @WaynnLue API 服务器将其作为字符串而非列表获取。 我是否必须将标题设置为“application/json”之类的? 相关:Python 3 urlopen context manager mocking 【参考方案1】:如果您的服务器期望 POST 请求是 json,那么您需要添加一个标头,并为您的请求序列化数据...
Python 2.x
import json
import urllib2
data =
'ids': [12, 3, 4, 5, 6]
req = urllib2.Request('http://example.com/api/posts/create')
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, json.dumps(data))
Python 3.x
https://***.com/a/26876308/496445
如果不指定header,则默认为application/x-www-form-urlencoded
类型。
【讨论】:
我有一个问题。是否可以在标题中添加多个项目...比如内容类型和客户端 ID...@jdi @OmarJandali,只需再次调用add_header()
,对于您要添加的每个标题。
我有以下编码,但它没有打印任何东西。它应该打印 url 和标题,但没有打印任何内容...req = urllib.Request('http://uat-api.synapsefi.com') req.add_header('X-SP-GATEWAY', 'client_id_asdfeavea561va9685e1gre5ara|client_secret_4651av5sa1edgvawegv1a6we1v5a6s51gv') req.add_header('X-SP-USER-IP', '127.0.0.1') req.add_header('X-SP-USER', '| ge85a41v8e16v1a618gea164g65') req.add_header('Content-Type', 'application/json') print(req)
...
urllib2 未被识别,所以我只使用了 urllib。我的请求也有错误。 The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead.
@jdi
@OmarJandali,请记住,这个答案最初是在 2012 年在 python 2.x 下给出的。您使用的是 Python3,因此导入会有所不同。现在是import urllib.request
和urllib.request.Request()
。此外,打印 req 对象并没有什么有趣的事情。通过打印req.headers
,您可以清楚地看到已添加标题。除此之外,我不知道为什么它在您的应用程序中不起作用。【参考方案2】:
我推荐使用令人难以置信的requests
模块。
http://docs.python-requests.org/en/v0.10.7/user/quickstart/#custom-headers
url = 'https://api.github.com/some/endpoint'
payload = 'some': 'data'
headers = 'content-type': 'application/json'
response = requests.post(url, data=json.dumps(payload), headers=headers)
【讨论】:
这给了我TypeError: post() takes from 1 to 2 positional arguments but 3 were given
不指定标题或调用json.dumps()
,只使用json=payload
(可能在很久以前编写此答案后就已经引入)要简洁得多。在此页面上查看其他答案。【参考方案3】:
对于 python 3.4.2,我发现以下方法可行:
import urllib.request
import json
body = 'ids': [12, 14, 50]
myurl = "http://www.testmycode.com"
req = urllib.request.Request(myurl)
req.add_header('Content-Type', 'application/json; charset=utf-8')
jsondata = json.dumps(body)
jsondataasbytes = jsondata.encode('utf-8') # needs to be bytes
req.add_header('Content-Length', len(jsondataasbytes))
response = urllib.request.urlopen(req, jsondataasbytes)
【讨论】:
Python3.6.2 这行得通。只有使用 req.add_header(...) 添加标题对我有用。 你不需要指定Content-Length
这个头,它会被urllib
自动计算出来。【参考方案4】:
如果 URL 包含查询字符串/参数值,这对 Python 3.5
非常有效,
请求网址 = https://bah2.com/ws/rest/v1/concept/ 参数值=21f6bb43-98a1-419d-8f0c-8133669e40ca
import requests
url = 'https://bahbah2.com/ws/rest/v1/concept/21f6bb43-98a1-419d-8f0c-8133669e40ca'
data = "name": "Value"
r = requests.post(url, auth=('username', 'password'), json=data)
print(r.status_code)
【讨论】:
在您的代码剪辑器中,headers 变量保持未使用状态 这个答案是不安全的。不要传递verify=False
,这会禁用证书验证并打开您的代码以遭受中间人攻击。
我从代码示例中删除了verify=False
以解决上述注释。【参考方案5】:
这是一个如何使用 Python 标准库中的 urllib.request 对象的示例。
import urllib.request
import json
from pprint import pprint
url = "https://app.close.com/hackwithus/3d63efa04a08a9e0/"
values =
"first_name": "Vlad",
"last_name": "Bezden",
"urls": [
"https://twitter.com/VladBezden",
"https://github.com/vlad-bezden",
],
headers =
"Content-Type": "application/json",
"Accept": "application/json",
data = json.dumps(values).encode("utf-8")
pprint(data)
try:
req = urllib.request.Request(url, data, headers)
with urllib.request.urlopen(req) as f:
res = f.read()
pprint(res.decode())
except Exception as e:
pprint(e)
【讨论】:
【参考方案6】:您必须添加标头,否则您将收到 http 400 错误。 代码在python2.6,centos5.4上运行良好
代码:
import urllib2,json
url = 'http://www.google.com/someservice'
postdata = 'key':'value'
req = urllib2.Request(url)
req.add_header('Content-Type','application/json')
data = json.dumps(postdata)
response = urllib2.urlopen(req,data)
【讨论】:
注意:这个答案已经很老了,urllib2
已在 Python 3 中删除。使用urllib
或requests
查找其他示例。【参考方案7】:
在最新的requests包中,可以使用requests.post()
方法中的json
参数发送一个json dict,并且header中的Content-Type
会被设置为application/json
。无需显式指定标头。
import requests
payload = 'key': 'value'
requests.post(url, json=payload)
【讨论】:
请注意,这将导致 POSTed json 带有单引号,这在技术上是无效的。 @Jethro 您在使用单引号时发现错误了吗?在 Python 中使用单引号是有效的。就我个人而言,我还没有遇到任何与此相关的问题。 抱歉我弄错了,我以为我的服务器正在接收单引号 JSON,但事实证明这是一个单独的问题和一些误导性的调试。干杯,这比手动指定标题要整洁得多!【参考方案8】:这个对我来说很好用 apis
import requests
data='Id':id ,'name': name
r = requests.post( url = 'https://apiurllink', data = data)
【讨论】:
这是一个错误的答案。data=data
参数发送一个 form-encoded 请求,它不是 JSON。请改用json=data
。【参考方案9】:
这里许多答案中使用的Requests 包很棒,但不是必需的。您可以使用 Python 3 标准库在一个步骤中简洁地执行 JSON 数据的 POST:
import json
from urllib import request
request.urlopen(request.Request(
'https://example.com/url',
headers='Content-Type': 'application/json',
data=json.dumps(
'pi': 3.14159
).encode()
))
如果您需要读取结果,您可以从返回的类文件对象中.read()
并使用json.loads()
解码JSON 响应。
【讨论】:
以上是关于如何以 JSON 格式发送 POST 请求?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# 在 POST 请求中发送 json 请求正文数据