Опублікуйте JSON за допомогою запитів Python


632

Мені потрібно розмістити JSON з клієнта на сервер. Я використовую Python 2.7.1 та simplejson. Клієнт використовує Запити. Сервер - CherryPy. Я можу отримати жорстко закодований JSON з сервера (код не показаний), але коли я намагаюся розмістити JSON на сервер, я отримую "400 поганий запит".

Ось мій код клієнта:

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)

Ось код сервера.

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())

Будь-які ідеї?


Я використовував позбавлену версію прикладу прямо з документації .
Чарльз R

Мій коментар все ще стоїть - CherryPy не називає __init__методи класу з contentаргументом (і не претендує на посилання, яке ви надаєте). У детальному прикладі, який вони мають, користувач надає код, який викликає __init__та надає аргументи, яких ми тут не бачили, тому я не маю уявлення, у якому стані знаходиться ваш об’єкт, коли ваш # this worksкоментар є релевантним.
Нік Бастін

1
Ви просите переглянути рядок, де створений екземпляр?
Чарльз Р

так, я намагався запустити ваш приклад для того, щоб перевірити його, і я не був впевнений, як ви його інстанціонували.
Нік Бастін

Код змінився. Зараз я створюю це без зайвих аргументів. cherrypy.quickstart(Root(), '/', conf).
Чарльз R

Відповіді:


1052

Починаючи з Запити версії 2.4.2 і далі, ви можете альтернативно використовувати параметр 'json' у виклику, що робить його більш простим.

>>> 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: Ця функція додана до офіційної документації. Ви можете переглянути його тут: Запрошує документацію


114
Я не можу повірити, скільки часу я витратив до того, як натрапив на твою відповідь. Документи запитів потрібно оновити, в jsonпараметрі немає абсолютно нічого . Мені довелося зайти в Github, перш ніж я побачив про нього будь-яку згадку: github.com/kennethreitz/requests/blob/…
IAmKale

1
Встановлюючи це на прийняту відповідь, оскільки це є більш ідіоматичним станом на 2.4.2. Майте на увазі, для божевільного unicode це може не спрацювати.
Чарльз Р

Я був у тому ж взутті, що і @IAmKale. Це полегшило головний біль, який у мене виникали за допомогою шлюзу API AWS. Він вимагає даних POST у форматі JSON за замовчуванням.
jstudios

1
Як дурень, я намагався використовувати параметр даних із застосуванням / json тип вмісту :(
Незаконний оператор

Я бачив приклад цього, який брав об'єкт dict і виконував json.dumps (object) перед відправкою. Не робіть цього ... це зіпсує ваш JSON. Сказане вище ідеально. Ви можете передати йому об'єкт пітон, і він перетвориться на ідеальний json.
MydKnight

376

Виявляється, мені не вистачало інформації заголовка. Наступні роботи:

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)

Хороший улов - Я бачив вашу application/jsonін GETі як - то пропустив , що ви не надали його на вимогу. Можливо, вам також доведеться переконатися, що ви щось повернете POSTабо ви можете отримати його 500.
Нік Бастін

Здається, це не потрібно. Коли друкую r, я отримую <Response [200]>.
Чарльз R

Як отримати цей json на стороні сервера?
VaidAbhishek

r = request.get (' localhost: 8080' ) c = r.content result = simplejson.loads (c)
Чарльз R

1
Маленькі головки до використання json.dumpsтут. dataПараметр requestsпрекрасно працює зі словниками. Не потрібно перетворювати на рядок.
Адвайт S

71

З запитів 2.4.2 ( https://pypi.python.org/pypi/requests ) підтримується параметр "json". Не потрібно вказувати "Тип вмісту". Отже, коротша версія:

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

29

Кращий спосіб:

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
Content-type: application/jsonє зайвим , оскільки json=вже натякає , що.
Моше

1
@Moshe повністю згоден, але щоб запитувати новішу версію Elasticsearch sever потрібно встановити Content-type
devesh

@Moshe, що робити, якщо тип вмісту text/html; charset=UTF-8. Тоді вище не буде працювати?
Ану

2
" Кращий спосіб " не публікувати відповіді WRONG через 3 роки після правильної відповіді. -1
CONvid19

3

Чудово працює з python 3.5+

клієнт:

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

сервер:

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

Який параметр між (data / json / files) слід використовувати, це насправді залежить від заголовка запиту з назвою ContentType (зазвичай перевіряйте це за допомогою інструментів розробника вашого браузера),

коли тип вмісту є програмою / x-www-form-urlencoded, код повинен бути:

requests.post(url, data=jsonObj)

коли тип вмісту є application / json, ваш код повинен бути одним із наведених нижче:

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

коли тип вмісту є багаточастинним / форма-даними, він використовується для завантаження файлів, тому ваш код повинен бути:

requests.post(url, files=xxxx)

Ісусе Христе, дякую. Я вивів волосся кілька хвилин тому.
Вагань Туманян

радий, що може вам допомогти
:)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.