在flask-restplus API中,我需要对已经使用api.model
定义了请求主体架构的请求JSON数据进行验证。基本上,我想将输入的JSON数据传递给API函数,在使用API函数之前,我必须先验证输入的JSON数据。为此,我使用RequestParser
来完成此任务,但是在验证和解析了请求JSON之后,API函数期望使用正确的JSON数据作为参数。要请求JSON验证,首先我必须解析接收到的输入JSON数据,解析其JSON主体,进行验证,然后将其重构为JSON对象,并传递给API函数。有没有更简单的方法可以做到这一点?
输入JSON数据
{
"body": {
"gender": "M",
"PCT": {
"value": 12,
"device": "roche_cobas"
},
"IL6": {
"value": 12,
"device": "roche_cobas"
},
"CRP": {
"value": 12,
"device": "roche_cobas"
}
}
}
我目前在烧瓶中的尝试
from flask_restplus import Api, Namespace, Resource, fields, reqparse, inputs
from flask import Flask, request, make_response, Response, jsonify
app = Flask(__name__)
api = Api(app)
ns = Namespace('')
feature = api.model('feature', {
'value': fields.Integer(required=True),
'time': fields.Date(required=True)
})
features = api.model('featureList', {
'age': fields.String,
'gender': fields.String(required=True),
'time': fields.Date,
'features': fields.List(fields.Nested(feature, required=True))
})
@ns.route('/hello')
class helloResource(Resource):
@ns.expect(features)
def post(self):
json_dict = request.json ## get input JSON data
## need to parse json_dict to validate expected argument in JSON body
root_parser = reqparse.RequestParser()
root_parser.add_argument('body', type=dict)
root_args = root_parser.parse_args()
jsbody_parser = reqparse.RequestParser()
jsbody_parser.add_argument('age', type=dict, location = ('body',))
jsbody_parser.add_argument('gender', type=dict, location=('body',))
## IL6, CRP could be something else, how to use **kwargs here
jsbody_parser.add_argument('IL6', type=dict, location=('body',))
jsbody_parser.add_argument('PCT', type=dict, location=('body',))
jsbody_parser.add_argument('CRP', type=dict, location=('body',))
jsbody_parser = jsbody_parser.parse_args(req=root_args)
## after validate each argument on input JSON request body, all needs to be constructed as JSON data
json_data = json.dumps(jsonify(jsbody_parser)) ## how can I get JSON again from jsbody_parser
func_output = my_funcs(json_data)
rest = make_response(jsonify(str(func_output)), 200)
return rest
if __name__ == '__main__':
api.add_namespace(ns)
app.run(debug=True)
更新:虚拟api函数
这里是伪函数,在验证后需要json数据:
import json
def my_funcs(json_data):
a =json.loads(json_data)
for k,v in a.iteritems():
print k,v
return jsonify(a)
上述尝试的当前输出:
我在响应正文中有此提示
{
"errors": {
"gender": "'gender' is a required property"
},
"message": "Input payload validation failed"
}
很明显,请求JSON输入在我的尝试中未得到处理和验证。我认为我必须将json_dict
传递给RequestParser对象,但仍然无法在此处验证请求JSON。如何做到这一点?
我必须从JSON主体验证期望的参数,验证之后,我想构造要用作API函数参数的JSON主体。我怎样才能做到这一点?任何解决此问题的方法?
解析的JSON必须传递给my_funcs
在我的帖子中,应解析请求JSON数据,例如age
,应将gender
验证为请求JSON中的预期参数,然后将添加的参数作为JSON进行JSON验证并传递{{1 }}。如何在fl中轻松实现这一点
我想确保flask应该解析JSON主体并按预期添加参数,否则抛出错误。例如:
my_funcs
如果我像上面那样提供JSON数据以向服务器端点发出POST请求,它应该给出错误。如何做到这一点?如何验证烧瓶API调用的POST请求JSON?
答案 0 :(得分:2)
当我试图在我们的对话中传达信息时,您似乎正在使用序列化和反序列化工具。我发现棉花糖是解决这个问题的出色工具(不是唯一的工具)。这是一个使用棉花糖验证请求主体,将验证后的数据转换回JSON字符串并将其传递给函数进行操作以及返回带有JSON数据的响应的工作示例:
from json import dumps, loads
from flask import Flask, jsonify, request
from marshmallow import Schema, fields, ValidationError
class BaseSchema(Schema):
age = fields.Integer(required=True)
gender = fields.String(required=True)
class ExtendedSchema(BaseSchema):
# have a look at the examples in the Marshmallow docs for more complex data structures, such as nested fields.
IL6 = fields.String()
PCT = fields.String()
CRP = fields.String()
def my_func(json_str:str):
""" Your Function that Requires JSON string"""
a_dict = loads(json_str)
return a_dict
app = Flask(__name__)
@app.route('/base', methods=["POST"])
def base():
# Get Request body from JSON
request_data = request.json
schema = BaseSchema()
try:
# Validate request body against schema data types
result = schema.load(request_data)
except ValidationError as err:
# Return a nice message if validation fails
return jsonify(err.messages), 400
# Convert request body back to JSON str
data_now_json_str = dumps(result)
response_data = my_func(data_now_json_str)
# Send data back as JSON
return jsonify(response_data), 200
@app.route('/extended', methods=["POST"])
def extended():
""" Same as base function but with more fields in Schema """
request_data = request.json
schema = ExtendedSchema()
try:
result = schema.load(request_data)
except ValidationError as err:
return jsonify(err.messages), 400
data_now_json_str = dumps(result)
response_data = my_func(data_now_json_str)
return jsonify(response_data), 200
这里有一些快速测试来显示验证,以及扩展请求正文中的字段:
import requests
# Request fails validation
base_data = {
'age': 42,
}
r1 = requests.post('http://127.0.0.1:5000/base', json=base_data)
print(r1.content)
# Request passes validation
base_data = {
'age': 42,
'gender': 'hobbit'
}
r2 = requests.post('http://127.0.0.1:5000/base', json=base_data)
print(r2.content)
# Request with extended properties
extended_data = {
'age': 42,
'gender': 'hobbit',
'IL6': 'Five',
'PCT': 'Four',
'CRP': 'Three'}
r3 = requests.post('http://127.0.0.1:5000/extended', json=extended_data)
print(r3.content)
希望这可以帮助您到达目的地。