flask-restx如何基于JSON Schema生成的model创建RequestParser
flask-restx 从JSON Schema生成RequestParser的实现方案
flask-restx本身没有原生支持从schema_model直接生成RequestParser的方法,但可以通过以下两种方案实现需求,避免重复编码:
方案1:直接获取校验后的请求数据(更推荐)
你调用@api.expect(request_model, validate=True)时,flask-restx已经自动完成了JSON Schema校验,非法请求会直接返回400错误,合法请求的请求体可以直接通过request.get_json()获取,完全不需要重复定义RequestParser,代码可以简化为:
from flask import request from flask_restx import Api, inputs, Resource api = Api(app, doc='/my_doc_path') request_schema = { 'type': 'object', 'properties': { 'param1': {'type': 'string'}, 'the_date': {"type": "string", "format": "date-time"}, }, 'required': ['param1'], } request_model = api.schema_model('my_api_model', request_schema) @api.route('/my_api/<string:id>') class MyApi(Resource): @api.expect(request_model, validate=True) def post(self, id): """ my cool app """ req_data = request.get_json() do_something(req_data['param1'], req_data['the_date'])
方案2:自定义转换函数生成RequestParser
如果需要做自动类型转换(比如把date-time格式的字符串转为datetime对象)、或者参数来自查询参数/表单等非JSON请求体场景,可以写通用转换函数,直接从JSON Schema或者已经生成的schema_model生成RequestParser:
通用转换函数实现
from flask_restx import reqparse, inputs # 基础类型映射 TYPE_MAPPING = { 'string': str, 'integer': int, 'number': float, 'boolean': bool } # 格式类型映射 FORMAT_MAPPING = { 'date-time': inputs.datetime_from_iso8601, 'date': inputs.date_from_iso8601, 'email': inputs.email, 'url': inputs.url } def schema_to_parser(schema, location='json'): """ 将JSON Schema转换为RequestParser对象 :param schema: JSON Schema字典,或者api.schema_model生成的model对象 :param location: 参数位置,可选json、args、form等 """ # 从schema_model中提取原始schema if hasattr(schema, '__schema__'): schema = schema.__schema__ parser = reqparse.RequestParser() required_fields = schema.get('required', []) # 遍历schema属性生成parser参数 for field_name, field_def in schema.get('properties', {}).items(): field_type = TYPE_MAPPING.get(field_def.get('type'), str) # 优先使用format对应的转换函数 if field_def.get('format') in FORMAT_MAPPING: field_type = FORMAT_MAPPING[field_def.get('format')] parser.add_argument( field_name, type=field_type, required=field_name in required_fields, help=field_def.get('description', f'参数{field_name}不符合要求'), location=location ) return parser
调用示例
@api.route('/my_api/<string:id>') class MyApi(Resource): @api.expect(request_model, validate=True) def post(self, id): """ my cool app """ parser = schema_to_parser(request_model) args = parser.parse_args() do_something(args['param1'], args['the_date'])
如果你的schema包含嵌套对象、数组等复杂结构,自行扩展上述转换函数的解析逻辑即可适配。
内容的提问来源于stack exchange,提问作者dina
相关产品推荐
相关产品推荐

