Como envio uma solicitação POST como JSON?

105
data = {
        'ids': [12, 3, 4, 5, 6 , ...]
    }
    urllib2.urlopen("http://abc.com/api/posts/create",urllib.urlencode(data))

Quero enviar uma solicitação POST, mas um dos campos deve ser uma lista de números. Como eu posso fazer isso ? (JSON?)

TIMEX
fonte
1
Mas já não é uma lista de números?
Waynn Lue
Isso não pode ser respondido sem saber que tipo de entrada a API espera.
Niklas B.
1
@WaynnLue o servidor API está recebendo isso como uma string, não uma lista.
TIMEX
1
Devo definir cabeçalhos como "application / json" ou algo assim?
TIMEX

Respostas:

154

Se o seu servidor espera que a solicitação POST seja json, você precisará adicionar um cabeçalho e também serializar os dados para sua solicitação ...

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


Se você não especificar o cabeçalho, ele será o application/x-www-form-urlencodedtipo padrão .

jdi
fonte
Eu tenho uma pergunta. é possível adicionar vários itens no cabeçalho ... como tipo de conteúdo e id do cliente ... @jdi
Omar Jandali
@OmarJandali, basta chamar add_header()novamente, para cada cabeçalho que você deseja adicionar.
jdi
eu tenho o seguinte codificado, mas não está imprimindo nada. era para imprimir o url e os cabeçalhos, mas nada foi impresso ... 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)...
Omar Jandali
O urllib2 não foi reconhecido, então usei apenas o urllib. Também estou recebendo um erro com a solicitação. The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead. @jdi
Omar Jandali
@OmarJandali, lembre-se de que esta resposta foi dada originalmente em 2012, em python 2.x. Você está usando Python3, então as importações serão diferentes. Agora seria import urllib.requeste urllib.request.Request(). Além disso, imprimir o objeto req não faz nada de interessante. Você pode ver claramente que os cabeçalhos foram adicionados ao imprimir req.headers. Além disso, não tenho certeza por que não está funcionando em seu aplicativo.
jdi
113

Eu recomendo usar o requestsmódulo incrível .

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)
FogleBird
fonte
Isso me dáTypeError: post() takes from 1 to 2 positional arguments but 3 were given
zakdances
66

para python 3.4.2 descobri que o seguinte funcionará:

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))
print (jsondataasbytes)
response = urllib.request.urlopen(req, jsondataasbytes)
microfone ouro
fonte
1
Python3.6.2 isso funcionou. Apenas adicionar cabeçalho com req.add_header (...) funcionou para mim.
Shalin LK
18

Isso funciona perfeitamente para Python 3.5, se o URL contiver valor de string / parâmetro de consulta,

URL de solicitação = https://bah2.com/ws/rest/v1/concept/
Valor do parâmetro = 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'), verify=False, json=data)
print(r.status_code)
MAX
fonte
7
em seu snipper de código, a variável headers permanece sem uso
atira em
4

Você precisa adicionar o cabeçalho ou obterá o erro http 400. O código funciona bem em python2.6, centos5.4

código:

    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)
YuanYe
fonte
2

Aqui está um exemplo de como usar o objeto urllib.request da biblioteca padrão do Python.

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)
Vlad Bezden
fonte
1

No último pacote de solicitações, você pode usar o jsonparâmetro no requests.post()método para enviar um dict json, e o Content-Typecabeçalho in será definido como application/json. Não há necessidade de especificar o cabeçalho explicitamente.

import requests

payload = {'key': 'value'}

requests.post(url, json=payload)
jdhao
fonte
Observe que isso resultará em JSON POSTADO com aspas simples, o que é tecnicamente inválido.
Jethro
@Jethro Você observou erros ao usar aspas simples? É válido usar aspas simples em Python. Pessoalmente, não encontrei nenhum problema em relação a isso.
jdhao
Aah desculpas, eu estava enganado, pensei que meu servidor estava recebendo JSON com aspas simples, mas acabou sendo um problema separado e alguma depuração enganosa. Saudações, isso é muito mais organizado do que especificar o cabeçalho manualmente!
Jethro
0

Este funciona bem para mim com apis

import requests

data={'Id':id ,'name': name}
r = requests.post( url = 'https://apiurllink', data = data)
Sudhir G
fonte