Kirim JSON menggunakan Permintaan Python

633

Saya perlu POST JSON dari klien ke server. Saya menggunakan Python 2.7.1 dan simplejson. Klien menggunakan Permintaan. Servernya adalah CherryPy. Saya dapat MENDAPATKAN JSON hard-kode dari server (kode tidak ditampilkan), tetapi ketika saya mencoba untuk POST JSON ke server, saya mendapatkan "400 Permintaan Buruk".

Ini kode klien saya:

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)

Ini adalah kode 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())

Ada ide?

Charles R
sumber
Saya menggunakan versi contoh langsung dari dokumentasi .
Charles R
Komentar saya masih berlaku - CherryPy tidak memanggil __init__metode kelas dengan contentargumen (dan tidak mengklaim dalam tautan yang Anda berikan). Dalam contoh terperinci yang mereka miliki, pengguna menyediakan kode yang memanggil __init__dan memberikan argumen, yang belum kita lihat di sini jadi saya tidak tahu keadaan objek Anda saat # this workskomentar Anda relevan.
Nick Bastin
1
Apakah Anda meminta untuk melihat baris di mana instance dibuat?
Charles R
ya, saya mencoba untuk memulai contoh Anda untuk mengujinya, dan saya tidak yakin bagaimana Anda membuat contoh itu.
Nick Bastin
Kode telah berubah. Saya sekarang membuatnya tanpa argumen tambahan. cherrypy.quickstart(Root(), '/', conf).
Charles R

Jawaban:

1053

Pada Permintaan versi 2.4.2 dan selanjutnya, Anda dapat menggunakan parameter 'json' sebagai alternatif dalam panggilan yang membuatnya lebih sederhana.

>>> 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: Fitur ini telah ditambahkan ke dokumentasi resmi. Anda dapat melihatnya di sini: Meminta dokumentasi

Zeyang Lin
sumber
114
Saya tidak percaya berapa banyak waktu yang saya buang sebelum menemukan jawaban Anda. The permintaan docs perlu ditingkatkan, ada benar-benar di jsonparameter. Saya harus pergi ke Github sebelum saya melihat disebutkannya: github.com/kennethreitz/requests/blob/…
IAmKale
1
Menyetel ini ke jawaban yang diterima karena ini lebih idiomatis pada 2.4.2. Ingat, untuk unicode gila, ini mungkin tidak berhasil.
Charles R
Saya berada di posisi yang sama dengan @IAkKale. Ini cukup meringankan sakit kepala yang saya alami dengan AWS's API Gateway. Ini membutuhkan data POST dalam format JSON secara default.
jstudios
1
Seperti orang bodoh saya mencoba menggunakan parameter data dengan aplikasi / json jenis konten :(
Operator Ilegal
Saya melihat contoh ini yang mengambil objek dict dan melakukan json.dumps (objek) sebelum mengirim. Jangan lakukan ini ... itu mengacaukan JSON Anda. Di atas sempurna .. Anda bisa memberikan objek python dan itu berubah menjadi json sempurna.
MydKnight
376

Ternyata saya melewatkan informasi header. Karya-karya berikut:

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)
Charles R
sumber
Baik menangkap - Saya melihat Anda application/jsondi GETdan entah bagaimana merindukan bahwa Anda tidak disediakan pada permintaan. Anda mungkin juga perlu memastikan bahwa Anda mengembalikan sesuatu dari POSTatau Anda mungkin mendapatkan 500.
Nick Bastin
Sepertinya tidak perlu. Ketika saya mencetak r, saya mengerti <Response [200]>.
Charles R
Bagaimana cara mengambil json ini di sisi server?
VaidAbhishek
r = requests.get (' localhost: 8080' ) c = r.content result = simplejson.loads (c)
Charles R
1
Kepala kecil sebelum digunakan di json.dumpssini. The dataparameter requestsbekerja dengan baik dengan kamus. Tidak perlu mengonversi ke string.
Advait S
71

Dari permintaan 2.4.2 ( https://pypi.python.org/pypi/requests ), parameter "json" didukung. Tidak perlu menentukan "Tipe-Konten". Jadi, versi yang lebih pendek:

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

Cara yang lebih baik adalah:

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)
ellen
sumber
18
yang Content-type: application/jsonberlebihan sebagai json=sudah mengisyaratkan bahwa.
Moshe
1
@ Moshe sepenuhnya setuju, tetapi untuk meminta versi yang lebih baru, Elasticsearch memutuskan untuk mengatur Content-type
devesh
@ Moshe, Bagaimana jika jenis konten text/html; charset=UTF-8. Maka di atas tidak akan berhasil?
Anu
2
" Cara yang lebih baik adalah " untuk tidak mengirim jawaban yang SALAH 3 tahun setelah jawaban yang benar. -1
CONvid19
3

Bekerja dengan sempurna dengan python 3.5+

klien:

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'}
Ruhil Jaiswal
sumber
3

Parameter antara (data / json / file) mana yang harus digunakan, itu sebenarnya tergantung pada header permintaan bernama ContentType (biasanya periksa ini melalui alat pengembang browser Anda),

ketika Content-Type adalah aplikasi / x-www-form-urlencoded, kode harus:

requests.post(url, data=jsonObj)

ketika Content-Type adalah aplikasi / json, kode Anda seharusnya adalah salah satu di bawah ini:

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

ketika Content-Type adalah multipart / form-data, itu digunakan untuk mengunggah file, jadi kode Anda seharusnya:

requests.post(url, files=xxxx)
Xiaoming
sumber
Yesus Kristus, terima kasih. Saya mencabut rambut saya beberapa saat yang lalu.
Vahagn Tumanyan
senang yang bisa membantu Anda
:)