Как отправить данные JSON с помощью запросов Python?

avatar
Charles R
16 марта 2012 в 07:46
1192763
9
852

Мне нужно отправить JSON от клиента на сервер. Я использую Python 2.7.1 и simplejson. Клиент использует запросы. Сервер CherryPy. Я могу ПОЛУЧИТЬ жестко запрограммированный JSON с сервера (код не показан), но когда я пытаюсь отправить JSON на сервер, я получаю сообщение «400 Bad Request».

Вот мой клиентский код:

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

Есть идеи?

Источник
Charles R
31 марта 2012 в 00:57
0

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

Nick Bastin
31 марта 2012 в 02:49
0

Мой комментарий все еще в силе - CherryPy не вызывает методы класса __init__ с аргументом content (и не претендует на это в предоставленной вами ссылке). В подробном примере, который у них есть, пользователь предоставляет код, который вызывает __init__ и предоставляет аргументы, которые мы здесь не видели, поэтому я понятия не имею, в каком состоянии находится ваш объект, когда ваш комментарий # this works актуален.

Charles R
31 марта 2012 в 03:19
1

Вы просите увидеть строку, в которой создается экземпляр?

Nick Bastin
31 марта 2012 в 04:02
0

да, я пытался запустить ваш пример, чтобы протестировать его, и я не был уверен, как вы его создавали.

Charles R
1 апреля 2012 в 05:39
0

Код изменился. Сейчас я создаю его без лишних аргументов. cherrypy.quickstart(Root(), '/', conf).

amiabl
7 июня 2019 в 12:56
0

В качестве альтернативы, если вы используете такой инструмент, как Postman для проверки вызовов API, вы можете сгенерировать фрагмент кода. Как фрагменты в Python, использующие пакет requests. Документация почтальона

Ответы (9)

avatar
Zeyang Lin
13 октября 2014 в 16:08
1432
Charles R
23 сентября 2015 в 23:00
2

Установив это на принятый ответ, поскольку это более идиоматично с версии 2.4.2. Имейте в виду, что для сумасшедшего юникода это может не сработать.

MydKnight
15 мая 2020 в 23:13
5

Я видел пример этого, который взял объект dict и выполнил json.dumps (объект) перед отправкой. Не делайте этого ... это испортит ваш JSON. Вышеупомянутое идеально ... вы можете передать ему объект python, и он превратится в идеальный json.

Boris
12 января 2021 в 18:18
5

@MydKnight, глядя на исходный код, Requests устанавливает тип контента, затем выполняет json.dumps(your_json) и преобразует результат из str в bytes.

avatar
isa
5 января 2022 в 14:09
3
headers = {"charset": "utf-8", "Content-Type": "application/json"}
url = 'http://localhost:PORT_NUM/FILE.php'

r = requests.post(url, json=YOUR_JSON_DATA, headers=headers)
print(r.text)
avatar
Birk Net
15 декабря 2021 в 22:05
0

Я решил это следующим образом:

from flask import Flask, request
from flask_restful import Resource, Api


req = request.json
if not req :
    req = request.form
req['value']
avatar
Raj
19 марта 2021 в 14:44
-1

Всегда рекомендуется иметь возможность читать файл JSON и анализировать объект как тело запроса. Мы не собираемся анализировать необработанные данные в запросе, поэтому следующий метод поможет вам решить эту проблему.

def POST_request():
    with open("FILE PATH", "r") as data:
        JSON_Body = data.read()
    response = requests.post(url="URL", data=JSON_Body)
    assert response.status_code == 200
avatar
xiaoming
12 апреля 2020 в 07:53
36

Какой параметр между data / json / files вам нужно использовать, зависит от заголовка запроса с именем Content-Type (вы можете проверить это с помощью инструментов разработчика вашего браузера).

Если Content-Type равен application/x-www-form-urlencoded , используйте data=:

requests.post(url, data=json_obj)

Если Content-Type равен application/json , вы можете либо просто использовать json=, либо использовать data= и установить Content-Type самостоятельно:

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

Когда Content-Type равен multipart/form-data , он используется для загрузки файлов, поэтому используйте files=:

requests.post(url, files=xxxx)
Olshansk
12 апреля 2021 в 20:54
0

+1. Если вы используете curlify для просмотра запроса, сделанного из ответа, заголовок типа контента не будет установлен, если вы не выполните эти инструкции. print(curlify.to_curl(project.request))

avatar
ellen
4 мая 2017 в 07:26
41

Лучше :

url = "http://xxx.xxxx.xx"
data = {
    "cardno": "6248889874650987",
    "systemIdentify": "s08",
    "sourceChannel": 12
}
resp = requests.post(url, json=data)
avatar
Ruhil Jaiswal
20 января 2017 в 21:10
7

Отлично работает с 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'}
avatar
ZZY
10 декабря 2014 в 10:08
79

Из запросов 2.4.2 (https://pypi.python.org/pypi/requests) поддерживается параметр «json». Нет необходимости указывать "Content-Type". Итак, более короткая версия:

requests.post('http://httpbin.org/post', json={'test': 'cheers'})
avatar
Charles R
31 марта 2012 в 03:26
444

Оказывается, мне не хватало информации заголовка. Следующие работы:

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)
Nick Bastin
31 марта 2012 в 04:01
0

Хороший улов - я видел ваш application/json в GET и как-то пропустил, что вы не предоставили его по запросу. Вам также может потребоваться вернуть что-то из POST, иначе вы можете получить 500.

Charles R
1 апреля 2012 в 05:36
0

Кажется, в этом нет необходимости. Когда я печатаю r, я получаю <Response [200]>.

VaidAbhishek
15 февраля 2013 в 12:01
0

Как мне получить этот json на стороне сервера?

Charles R
11 мая 2013 в 18:15
0

r = requests.get ('localhost: 8080') c = r.content result = simplejson.loads (c)

Advait S
2 июля 2018 в 06:32
2

Немного подумайте, прежде чем использовать здесь json.dumps. Параметр data из requests отлично работает со словарями. Нет необходимости преобразовывать в строку.

Geordie
16 июля 2018 в 20:58
0

Это был лучший ответ для меня, поскольку встроенная поддержка json запросов использует встроенную поддержку json в Python, которая не может обрабатывать мои типы объектов. Поэтому мне нужно было использовать jsonpickle и вручную установить тип носителя json.

Safeer Abbas
8 января 2021 в 15:32
0

да, json.dumps (data) - очень эффективный и удивительный способ сделать это.