【问题标题】:How do I send a POST request as a JSON?如何以 JSON 格式发送 POST 请求?
【发布时间】: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 json http url post


【解决方案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://stackoverflow.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 响应。

    【讨论】:

      猜你喜欢
      • 2014-04-10
      • 1970-01-01
      • 1970-01-01
      • 2022-02-21
      • 2011-09-07
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多