Python Flask-Restful POST не принимает аргументы JSON
Я очень новичок в Flask (& Flask-Restful).
Моя проблема: аргументы json
для POST
получают значение NONE
(не работает).
Я могу принимать аргументы из form-data
, используя плагин POSTMAN
для хром. Но, когда я переключаюсь на raw
(& feed a 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
: { "username": "hello", "password": "world" }
Output
: { "p": "None", "u": "None" }
Проверенные вещи # 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
: { "username": "hello", "password": "world" }
Output
: { "p": "None", "u": "None" }
PS:
Я буду постоянно обновлять свой вопрос с каждой неудачной попыткой.
Пожалуйста, дайте мне знать, если вам нужна дополнительная информация, чтобы сделать этот вопрос более понятным.
Ответы
Ответ 1
В соответствии с документацией для Request.json и новой Request.get_json, у вас должен быть тип mimetype в вашем запросе POST, установленном на application/json
. Это единственный способ, с помощью которого флажок автоматически анализирует ваши данные JSON в свойстве Request.json
, который, как мне кажется, зависит от того, что Flask-Restful зависит от получения данных JSON.
ПРИМЕЧАНИЕ. Более новая функция get_json
имеет возможность принудительно анализировать данные POST как JSON независимо от типа mimetype
Ответ 2
Ответ на 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)
Ответ 3
Я столкнулся с подобной проблемой, и вот решение, которое работает для меня. скажем, ваше приложение выглядит так:
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
как показано выше.
Ответ 4
После форсирования запроса на разбор 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)