Python Flask-Restful POST не принимает аргументы JSON

Я очень новичок в Flask (и Flask-Restful).

Моя проблема: json аргументы для POST устанавливаются на NONE (не работают).

Я могу брать аргументы из form-data, используя плагин POSTMAN для chrome. Но когда я переключаюсь на raw (и подаю json), он не может прочитать json и присваивает NONE всем моим аргументам.

Я прочитал некоторые связанные сообщения stackoverflow, связанные с этим: link1, link2, link3 ... ни один из них мне не помог.

Я использую python-2.6, Flask-Restful-0.3.3, Flask-0.10.1, Chrome, POSTMAN в Oracle Linux 6.5.

Код Python app.py :

from flask import Flask, jsonify
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)

class HelloWorld(Resource):
    def post(self):
        args = parser.parse_args()
        un = str(args['username'])
        pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5444 ,debug=True)

Проверка с использованием POSTMAN :

  • Использование form-data: работает отлично!
  • Использование raw -> json : вызывает эту проблему

Попытки №1 :

Добавьте параметр json к моему методу add_argument() в app.py

parser = reqparse.RequestParser()
parser.add_argument('username', type=str, location='json') # added json
parser.add_argument('password', type=str, location='json') # added json

Input : { "имя пользователя": "привет", "пароль": "мир" }

Output : { "p": "Нет", "u": "Нет" }

Попытки №2:

Измените тип на unicode в методе add_argument() в app.py

parser = reqparse.RequestParser()
parser.add_argument('username', type=unicode, location='json') # change type to unicode
parser.add_argument('password', type=unicode, location='json') # change type to unicode

Input : { "имя пользователя": "привет", "пароль": "мир" }

Output : { "p": "Нет", "u": "Нет" }


PS: я буду обновлять свой вопрос при каждой неудачной попытке. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация, чтобы сделать этот вопрос более ясным.


person sudhishkr    schedule 27.05.2015    source источник
comment
Мне кажется, вы пропустили звонок parser.parse_args(). У вас должно быть args = parser.parse_args(), прежде чем вы сможете получить доступ к args   -  person junnytony    schedule 27.05.2015
comment
@junnytony - это опечатка с моей стороны, я забыл скопировать эту строку. Срочно редактирую вопрос!   -  person sudhishkr    schedule 27.05.2015
comment
Попробуйте unicode вместо str для типов аргументов   -  person sirfz    schedule 27.05.2015
comment
@Sir_FZ unicode имеет ту же проблему, сохраняет None   -  person sudhishkr    schedule 27.05.2015


Ответы (4)


Согласно документации для Request.json и новым Request.get_json, у вас должен быть MIME-тип в вашем POST запрос установлен на application/json. Это единственный способ, которым flask будет автоматически анализировать ваши данные JSON в свойстве Request.json, от которого (я полагаю) зависит Flask-Restful для получения данных JSON.

ПРИМЕЧАНИЕ. Более новая функция get_json имеет возможность принудительно анализировать данные POST как JSON независимо от MIME-типа.

person junnytony    schedule 27.05.2015

Ответ junnytony дал мне подсказку, и я продолжил этот подход. get_json, кажется, добился цели.

from flask import Flask, jsonify, request
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

#parser = reqparse.RequestParser()
#parser.add_argument('username', type=unicode, location='json')
#parser.add_argument('password', type=unicode, location='json')

class HelloWorld(Resource):
    def post(self):
        json_data = request.get_json(force=True)
        un = json_data['username']
        pw = json_data['password']
        #args = parser.parse_args()
        #un = str(args['username'])
        #pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5444 ,debug=True)
person sudhishkr    schedule 27.05.2015
comment
Хороший :). но я думаю, что ваш код был бы еще более удивительным, если бы вы изменили тип mime для своего сообщения на «application/json». Я предполагаю, что вы используете AJAX для своего сообщения. С помощью чего-то вроде jQuery вы можете легко добавить соответствующий MIME-тип, например, веб-служба"> stackoverflow.com/questions/6323338/ - person junnytony; 28.05.2015
comment
Спасибо за предоставление вашего окончательного кода, у меня есть аналогичный вариант использования. - person Briford Wylie; 17.07.2015
comment
Привет, я также столкнулся с той же проблемой. Согласно вашему предложению, я сделал, но все еще получаю ошибку неправильного запроса. - person KCN; 13.06.2017
comment
какова ваша точная проблема @KCN? - person sudhishkr; 13.06.2017
comment
В соответствии с вашим предложением я последовал примеру json_dat = request.get_json(force=True) fname = json_dat[firstname] lname = json_dat[lastname], но при выполнении этого URL-адреса из остального клиента возникает ошибка 400 неверных запросов - person KCN; 14.06.2017

После форсирования запроса на разбор json у меня заработало. Вот код:

from flask import Flask, jsonify, request
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)

class HelloWorld(Resource):
    def post(self):
        request.get_json(force=True)
        args = parser.parse_args()
        un = str(args['username'])
        pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5444 ,debug=True)
person moutaz samir    schedule 22.05.2019

Я столкнулся с подобной проблемой, и вот решение, которое работает для меня. скажем, ваше приложение выглядит так:

from flask import Flask, jsonify
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
api = Api(app)

# Define parser and request args
parser = reqparse.RequestParser()
parser.add_argument('last_name', type=str)
parser.add_argument('first_name', type=str)
# not the type=dict
parser.add_argument('personal_data', type=dict)


class Item(Resource):

    def post(self):

        args = parser.parse_args()

        ln = args['last_name']
        fn = args['first_name']
        # we can also easily parse nested structures
        age = args['personal_data']['age']
        nn = args['personal_data']['nicknames']

        return jsonify(fn=fn, ln=ln, age=age, nn=nn)


api.add_resource(Item, '/item')

if __name__ == '__main__':
    app.run(debug=True)

Теперь вы можете легко создать некоторые данные JSON:

import json

d = {'last_name': 'smith', 'first_name': 'john', 'personal_data': {'age': 18, 'height': 180, 'nicknames': ['johnny', 'grandmaster']}}

print(json.dumps(d, indent=4))

{
    "last_name": "smith",
    "first_name": "john",
    "personal_data": {
        "age": 18,
        "height": 180,
        "nicknames": [
            "johnny",
            "grandmaster"
        ]
    }
}

json.dumps(d)
'{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

и вызовите приложение:

curl http://localhost:5000/item -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

Это вылетит с ошибкой (я сократил трассировку):

age = args['personal_data']['age']
TypeError: объект 'NoneType' не поддерживает подписку

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

-H "Content-Type: application/json"

а потом позвони

curl http://localhost:5000/item -H "Content-Type: application/json" -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

Вывод выглядит так, как ожидалось:

{
  "age": 18, 
  "fn": "john", 
  "ln": "smith", 
  "nn": [
    "johnny", 
    "grandmaster"
  ]
}

Функцию также можно упростить до:

class Item(Resource):

    def post(self):

        json_data = request.get_json()
        # create your response below

как показано выше.

person Cleb    schedule 26.01.2019