如何以 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.requesturllib.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 中删除。使用urllibrequests 查找其他示例。【参考方案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 请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何以json的格式发送到前端

使用 RestKit 以 XML 格式发送 post 请求

如何使用 C# 在 POST 请求中发送 json 请求正文数据

使用 POST 请求 iOS Swift 3 发送嵌套 JSON

PHP如何通过Post请求发送Json数据

如何通过 Postman 以 JSON 格式在请求正文中发送对象数组?