Python Flask-Restful POST 不采用 JSON 参数
Posted
技术标签:
【中文标题】Python Flask-Restful POST 不采用 JSON 参数【英文标题】:Python Flask-Restful POST not taking JSON arguments 【发布时间】:2015-08-10 02:13:17 【问题描述】:我对 Flask(和 Flask-Restful)非常陌生。
我的问题:POST
的 json
参数设置为 NONE
(不起作用)。
我可以使用 POSTMAN
chrome 插件从 form-data
获取参数。但是,当我切换到raw
(并提供json
)时,它无法读取json并为我的所有参数分配NONE
。
我已经阅读了一些与此相关的 *** 帖子:link1、link2、link3 ...这些都没有帮助我。
我在 Oracle Linux 6.5 上使用 python-2.6
、Flask-Restful-0.3.3
、Flask-0.10.1
、Chrome
、POSTMAN
。
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:
在app.py
中将json
参数添加到我的add_argument()
方法中
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”:“无”,“u”:“无”
尝试#2:
在app.py
中的add_argument()
方法中将类型更改为unicode
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”:“无”,“u”:“无”
PS: 我会不断更新我的问题,每次失败的尝试。 如果您需要更多信息以使这个问题更清楚,请告诉我。
【问题讨论】:
在我看来,您好像错过了对parser.parse_args()
的呼叫。您应该先拥有args = parser.parse_args()
,然后才能访问args
@junnytony - 这是我这边的错字,我忘了复制那行。立即编辑问题!
对参数类型尝试unicode
而不是str
@Sir_FZ unicode
有同样的问题,保留None
【参考方案1】:
在强制请求解析 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)
【讨论】:
【参考方案2】:我遇到了类似的问题,这里有一个适合我的解决方案。假设您的应用程序如下所示:
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"]'
这将因错误而崩溃(我缩短了回溯):
年龄 = 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
作为shown above。
【讨论】:
【参考方案3】:根据Request.json 和新Request.get_json 的文档,您应该将POST 请求的mimetype 设置为application/json
。这是 Flask 自动将您的 JSON 数据解析为 Request.json
属性的唯一方法,(我相信)这是 Flask-Restful 检索 JSON 数据所依赖的。
注意:较新的 get_json
函数具有一个选项,可以强制将 POST 数据解析为 JSON,而不管 MIME 类型如何
【讨论】:
【参考方案4】: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)
【讨论】:
很好:)。但我认为如果您将帖子的 mimetype 更改为“application/json”,您的代码会更加出色。我猜你正在为你的帖子使用 AJAX。使用 jQuery 之类的东西,您可以轻松添加适当的 mimetype,例如 ***.com/questions/6323338/… 感谢您提供最终代码,我有一个类似的用例。 您好,我也面临同样的问题。根据您的建议,我完成了但仍然收到错误的请求错误 你的具体问题是什么@KCN? 根据你的建议,我遵循了 json_dat = request.get_json(force=True) fname = json_dat["firstname"] lname = json_dat["lastname"] 但是在从休息客户端执行这个 url 时400 错误请求错误以上是关于Python Flask-Restful POST 不采用 JSON 参数的主要内容,如果未能解决你的问题,请参考以下文章
七十六:flask.Restful之flask-Restful插件的基本使用
python 具有Flask-Restful的基本API服务器
使用 python flask-restful 和消费 AngularJS(使用 $http)时出现 CORS(跨源...)错误