Pubblica JSON usando le richieste Python


633

Devo inviare un JSON da un client a un server. Sto usando Python 2.7.1 e simplejson. Il client utilizza le richieste. Il server è CherryPy. Posso ottenere un JSON hardcoded dal server (codice non mostrato), ma quando provo a POSTARE un JSON sul server, ottengo "400 Bad Request".

Ecco il mio codice cliente:

data = {'sender':   'Alice',
    'receiver': 'Bob',
    'message':  'We did it!'}
data_json = simplejson.dumps(data)
payload = {'json_payload': data_json}
r = requests.post("http://localhost:8080", data=payload)

Ecco il codice del server.

class Root(object):

    def __init__(self, content):
        self.content = content
        print self.content  # this works

    exposed = True

    def GET(self):
        cherrypy.response.headers['Content-Type'] = 'application/json'
        return simplejson.dumps(self.content)

    def POST(self):
        self.content = simplejson.loads(cherrypy.request.body.read())

Qualche idea?


Stavo usando una versione ridotta di un esempio direttamente dalla documentazione .
— Charles R

Il mio commento è ancora valido: CherryPy non chiama i __init__metodi di classe con un contentargomento (e non rivendica il link fornito). Nell'esempio dettagliato che hanno, l'utente fornisce il codice che chiama __init__e fornisce gli argomenti, che non abbiamo visto qui, quindi non ho idea dello stato in cui si trova il tuo oggetto quando il tuo # this workscommento è rilevante.
— Nick Bastin,

1
Stai chiedendo di vedere la riga in cui viene creata l'istanza?
— Charles R

sì, stavo provando ad avviare il tuo esempio per testarlo, e non ero sicuro di come lo stavi istanziando.
— Nick Bastin,

Il codice è cambiato Ora lo sto creando senza l'argomento in più. cherrypy.quickstart(Root(), '/', conf).
— Charles R

Risposte:


1053

A partire dalla versione 2.4.2 e successive, è possibile utilizzare il parametro "json" nella chiamata in modo da semplificarlo.

>>> import requests
>>> r = requests.post('http://httpbin.org/post', json={"key": "value"})
>>> r.status_code
200
>>> r.json()
{'args': {},
 'data': '{"key": "value"}',
 'files': {},
 'form': {},
 'headers': {'Accept': '*/*',
             'Accept-Encoding': 'gzip, deflate',
             'Connection': 'close',
             'Content-Length': '16',
             'Content-Type': 'application/json',
             'Host': 'httpbin.org',
             'User-Agent': 'python-requests/2.4.3 CPython/3.4.0',
             'X-Request-Id': 'xx-xx-xx'},
 'json': {'key': 'value'},
 'origin': 'x.x.x.x',
 'url': 'http://httpbin.org/post'}

EDIT: questa funzione è stata aggiunta alla documentazione ufficiale. Puoi visualizzarlo qui: richiede documentazione


114
Non riesco a credere quanto tempo ho perso prima di imbattermi nella tua risposta. I documenti delle richieste devono essere aggiornati, non c'è assolutamente nulla sul jsonparametro. Ho dovuto entrare in Github prima di
— vederne la

1
Impostandolo sulla risposta accettata poiché è più idiomatica a partire dalla 2.4.2. Tieni presente che, per un pazzo Unicode, questo potrebbe non funzionare.
— Charles R

Ero nei panni di @IAmKale. Questo ha alleviato il mal di testa che avevo con il gateway API di AWS. Richiede i dati POST in formato JSON per impostazione predefinita.
— jstudios,

1
Come un pazzo ho provato a usare il parametro data con application / json il tipo di contenuto :(
— Operatore illegale

Ho visto un esempio di questo che ha preso l'oggetto dict ed eseguito json.dumps (oggetto) prima di inviarlo. Non farlo ... rovina il tuo JSON. Quanto sopra è perfetto..puoi passargli un oggetto pitone e si trasforma in json perfetto.
— MydKnight

376

Si scopre che mi mancavano le informazioni di intestazione. Le seguenti opere:

url = "http://localhost:8080"
data = {'sender': 'Alice', 'receiver': 'Bob', 'message': 'We did it!'}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
r = requests.post(url, data=json.dumps(data), headers=headers)

Buona cattura - Ho visto il tuo application/jsonin GETe in qualche modo mancato che non aveva fornito su richiesta. Potresti anche aver bisogno di assicurarti di restituire qualcosa da POSTo potresti ricevere un 500.
— Nick Bastin,

Non sembra essere necessario. Quando stampo r, ottengo <Response [200]>.
— Charles R

Come posso recuperare questo json sul lato server?
— VaidAbhishek,

r = richieste.get (' localhost: 8080' ) c = risultato contenuto r = contenuto = simplejson.loads (c)
— Charles R

1
Il piccolo testa in alto prima di usare json.dumpsqui. Il dataparametro di requestsfunziona bene con i dizionari. Non è necessario convertirlo in una stringa.
— Advait S

71

Dalle richieste 2.4.2 ( https://pypi.python.org/pypi/requests ), è supportato il parametro "json". Non è necessario specificare "Tipo di contenuto". Quindi la versione più breve:

requests.post('http://httpbin.org/post', json={'test': 'cheers'})

29

Il modo migliore è :

url = "http://xxx.xxxx.xx"

datas = {"cardno":"6248889874650987","systemIdentify":"s08","sourceChannel": 12}

headers = {'Content-type': 'application/json'}

rsp = requests.post(url, json=datas, headers=headers)

18
la Content-type: application/jsonè ridondante come json=accenna già che.
— Moshe,

1
@Moshe è totalmente d'accordo, ma per richiedere la versione più recente è necessario impostare Elasticsearch sever Content-type
— devesh

@Moshe, cosa succede se il tipo di contenuto è text/html; charset=UTF-8. Quindi sopra non funzionerà?
— Anu,

2
" Il modo migliore è " non pubblicare risposte ERRATE 3 anni dopo una risposta corretta. -1
— CONvid19

3

Funziona perfettamente con Python 3.5+

cliente:

import requests
data = {'sender':   'Alice',
    'receiver': 'Bob',
    'message':  'We did it!'}
r = requests.post("http://localhost:8080", json={'json_payload': data})

server:

class Root(object):

    def __init__(self, content):
        self.content = content
        print self.content  # this works

    exposed = True

    def GET(self):
        cherrypy.response.headers['Content-Type'] = 'application/json'
        return simplejson.dumps(self.content)

    @cherrypy.tools.json_in()
    @cherrypy.tools.json_out()
    def POST(self):
        self.content = cherrypy.request.json
        return {'status': 'success', 'message': 'updated'}

3

Quale parametro tra (data / json / files) dovrebbe essere usato, in realtà dipende da un'intestazione di richiesta denominata ContentType (di solito controlla questo tramite gli strumenti di sviluppo del tuo browser),

quando Content-Type è application / x-www-form-urlencoded, il codice dovrebbe essere:

requests.post(url, data=jsonObj)

quando Content-Type è application / json, il codice dovrebbe essere uno dei seguenti:

requests.post(url, json=jsonObj)
requests.post(url, data=jsonstr, headers={"Content-Type":"application/json"})

quando Content-Type è multipart / form-data, viene utilizzato per caricare file, quindi il tuo codice dovrebbe essere:

requests.post(url, files=xxxx)

Gesù Cristo, grazie. Mi stavo togliendo i capelli qualche istante fa.
— Vahagn Tumanyan,

felice che ti possa aiutare
— :)
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.