Come invio una richiesta POST come JSON?


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

Voglio inviare una richiesta POST, ma uno dei campi dovrebbe essere un elenco di numeri. Come lo posso fare ? (JSON?)


1
Non è già un elenco di numeri, però?
Waynn Lue

Non è possibile rispondere senza sapere che tipo di input si aspetta l'API.
Niklas B.

1
@WaynnLue il server API lo riceve come una stringa, non come un elenco.
TIMEX

1
Devo impostare le intestazioni come "application / json" o qualcosa del genere?
TIMEX

Risposte:


154

Se il tuo server si aspetta che la richiesta POST sia json, dovrai aggiungere un'intestazione e serializzare anche i dati per la tua richiesta ...

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 non specifichi l'intestazione, sarà il application/x-www-form-urlencodedtipo predefinito .


Ho una domanda. è possibile aggiungere più elementi nell'intestazione ... come tipo di contenuto e ID client ... @jdi
Omar Jandali

@OmarJandali, chiama di add_header()nuovo, per ogni intestazione che desideri aggiungere.
jdi

ho il codice seguente ma non stampa nulla. avrebbe dovuto stampare l'URL e le intestazioni ma non è stato stampato nulla ... 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

urllib2 non è stato riconosciuto, quindi ho usato solo urllib. Inoltre ricevo un errore con la richiesta. The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead. @jdi
Omar Jandali

@OmarJandali, tieni presente che questa risposta è stata originariamente data nel 2012, con python 2.x. Stai usando Python3 quindi le importazioni saranno diverse. Ora sarebbe import urllib.requeste urllib.request.Request(). Inoltre, la stampa dell'oggetto req non fa nulla di interessante. Puoi vedere chiaramente che le intestazioni sono state aggiunte stampando req.headers. Oltre a ciò, non sono sicuro del motivo per cui non funziona nella tua applicazione.
jdi


66

per python 3.4.2 ho scoperto che quanto segue funzionerà:

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)

1
Python3.6.2 ha funzionato. Solo l'aggiunta di intestazione con req.add_header (...) ha funzionato per me.
Shalin LK

18

Funziona perfettamente per Python 3.5, se l'URL contiene la stringa di query / il valore del parametro,

URL richiesta = https://bah2.com/ws/rest/v1/concept/
Valore parametro = 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)

7
nello snipper di codice, la variabile delle intestazioni rimane inutilizzata
visualizzato l'

4

Devi aggiungere un'intestazione o otterrai un errore http 400. Il codice funziona bene su python2.6, centos5.4

codice:

    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)

2

Ecco un esempio di come utilizzare l'oggetto urllib.request dalla libreria standard di 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)

1

Nell'ultimo pacchetto di richieste, è possibile utilizzare il jsonparametro in requests.post()metodo per inviare un dict json e l' Content-Typeintestazione in verrà impostata su application/json. Non è necessario specificare l'intestazione in modo esplicito.

import requests

payload = {'key': 'value'}

requests.post(url, json=payload)

Si noti che ciò risulterà in json POST con virgolette singole, che è tecnicamente non valido.
Jethro

@ Jethro Hai notato errori nell'uso delle virgolette singole? È valido utilizzare virgolette singole in Python. Personalmente, non ho riscontrato alcun problema al riguardo.
jdhao

Aah mi scuso, mi sbagliavo, pensavo che il mio server stesse ricevendo JSON con virgolette singole, ma si è rivelato essere un problema separato e un debug fuorviante. Salute, è molto più ordinato che dover specificare manualmente l'intestazione!
Jethro

0

Questo funziona bene per me con le API

import requests

data={'Id':id ,'name': name}
r = requests.post( url = 'https://apiurllink', data = data)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.