flask接口参数校验 jsonschema 的使用

开头

flask接口开发中参数校验可以用到的方法有很多,但是我比较喜欢跟前端的js检验类似,故选用到了 jsonschema 这个参数校验的库

Demo

下面是一个比较全的参数校验的接口,日后方便参考 官方链接 http://json-schema.org/learn/getting-started-step-by-step

from jsonschema import validate, ValidationError # 导入参数的包

@app.route('/login4', methods=['POST'])
def login4():
    body = request.get_json()
    try:
        validate(
            body,
            {
                "$schema": "http://json-schema.org/learn/getting-started-step-by-step",
                # 描述对应的JSON元素,title相对来说,更加简洁
                "title": "book info",
                # 描述对应的JSON元素,description更加倾向于详细描述相关信息
                "description": "some information about book",
                # 该关键字用于限定待校验JSON元素所属的数据类型,取值可为:object,array,integer,number,string,boolean,null
                "type": "object",
                # 用于指定JSON对象中的各种不同key应该满足的校验逻辑,
                # 如果待校验JSON对象中所有值都能够通过该关键字值中定义的对应key的校验逻辑,每个key对应的值,都是一个JSON Schema,则待校验JSON对象通过校验。
                "properties": {
                    "id": {
                        "description": "The unique identifier for a book",
                        "type": "integer",
                        "minimum": 1
                    },
                    "name": {
                        "description": "book name",
                        "type": "string",
                        "minLength": 3,
                        "maxLength": 30
                    },
                    "info": {
                        "description": "simple information about book",
                        "type": "string",
                        "minLength": 10,
                        "maxLength": 60
                    },
                    "tips": {
                        "anyOf": [  # 满足其中一个类型 就行
                            {"type": "string", "minLength": 10, "maxLength": 60}, 
                            {"type": "number", "minimum": 5.0}
                        ]
                    },
                    "price": {
                        "description": "book price",
                        "type": "number",
                        # 能被0.5整除
                        "multipleOf": 0.5,
                        # 这里取等,5.0=<price<=99999.0
                        "minimum": 5.0,
                        "maximum": 99999.0,
                        # 若使用下面这两个关键字则 5.0<price<99999.0
                        # "exclusiveMinimum": 5.0,
                        # "exclusiveMaximum": 99999.0
                    },
                    "tags": {
                        "type": "array",
                        "items": [
                            {
                                "type": "string",
                                "minLength": 2,
                                "maxLength": 8
                            },
                            {
                                "type": "number",
                                "minimum": 1.0
                            }
                        ],
                        # 待校验JSON数组第一个元素是string类型,且可接受的最短长度为5个字符,第二个元素是number类型,且可接受的最小值为10
                        # 剩余的其他元素是string类型,且可接受的最短长度为2。
                        "additonalItems": {
                            "type": "string",
                            "miniLength": 2
                        },
                        # 至少一个
                        "miniItems": 1,
                        # 最多5个
                        "maxItems": 5,
                        # 值为true时,所有元素都具有唯一性时,才能通过校验。
                        "uniqueItems": True
                    },
                    "date": {
                        "description": "书籍出版日期",
                        "type": "string",
                        # 可以是以下取值:date、date-time(时间格式)、email(邮件格式)、hostname(网站地址格式)、ipv4、ipv6、uri等。
                        # 使用format关键字时,在实例化validator时必须给它传format_checker参数,值如:draft7_format_checker, 网址:
                        # https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft7Validator
                        "format": "date",
                    },
                    "bookcoding": {
                        "description": "书籍编码",
                        "type": "string",
                        # 符合该关键字指定的正则表达式,才算通过校验。
                        "pattern": "^[A-Z]+[a-zA-Z0-9]{12}$"
                    },
                    "other": {
                        "description": "其他信息",
                        "type": "object",
                        "properties": {
                            "info1": {
                                "type": "string"
                            },
                            "info2": {
                                "type": "string"
                            }
                        }
                    }
                },
                # 指定了待校验JSON对象可以接受的最少 一级key 的个数
                "minProperties": 3,
                # 指定了待校验JSON对象可以接受的最多 一级key 的个数。
                "maxProperties": 7,
                # patternProperties对象的每一个一级key都是一个正则表达式,value都是一个JSON Schema。
                # 只有待校验JSON对象中的一级key,通过与之匹配的patternProperties中的一级正则表达式,对应的JSON Schema的校验,才算通过校验。
                # 下面的JSON Schema表示, 所有以a开头的一级key的value都必须是number,
                "patternProperties": {
                    "^a": {
                        "type": "number"
                    },
                },
                # 如果待校验JSON对象中存在,既没有在properties中被定义,又没有在patternProperties中被定义,那么这些一级key必须通过additionalProperties的校验。
                "additionalProperties": {
                    "desc": {
                        "type": "string",
                        "minLength": 1
                    },
                },
                # 该关键字限制了JSON对象中必须包含哪些一级key。
                # 如果一个JSON对象中含有required关键字所指定的所有一级key,则该JSON对象能够通过校验。
                "required": ["id", "name", "info", "price"]
            })
    
    except ValidationError as e:
        msg = "json数据不符合schema规定:\n出错字段:{}\n提示信息:{}".format(" --> ".join([i for i in e.path]), e.message)
        print(msg)
        return jsonify(status=500, msg=msg)
        
    print(body)
    title = body.get('title')
    return '1'

添加一个数组里面包含字典的参数检验

# 周报添加游戏
@platform_blue.route('/add_week_game', methods=["POST"])
def add_week_game():
    body = request.get_json()
    try:
        validate(body, {
            'type': 'object',
            "description": "添加", # 参数建议,添加数组里面包含字典的
            'properties': {
                "data_lists": {
                        "type": "array",
                        "items": {
                            "type":"object",
                            "required":["a", "b"],
                            "properties":{
                                "a":{"type":"string", "minLength":1},
                                "b":{"type":"string", "minLength":1},
                            }}
                        },
                "user_id":{
                    "description": "用户id",
                    'type': 'integer'
                },
                "id":{
                    "description": "用户id",
                    'type': 'integer'
                }
            },
            'required': ['data_lists', 'user_id', 'id']
        })
    except ValidationError as e:
        print(e)
        # msg = "参数不符合规定;{} 提示信息: {}".format(" --> ".join([i for i in e.path]), e.message)
        # print(msg)
        return jsonify(status=RET.OK, msg=e)

完。

posted @ 2021-06-16 12:11  陈科科  阅读(1169)  评论(2编辑  收藏  举报