通常,我们在开发Web应用时,会使用jsonschema对Request入参进行校验。
那么如果仅是常规的Python函数,又该如何进行校验。
我们希望能够做到:
对业务代码侵入性小; 校验代码与业务代码通过约定进行匹配,可以独立调整; 代码阅读流畅。自然地我想到使用Python的装饰器来实现。
先放出装饰器代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import functools
import inspect
from typing import Callable
from jsonschema import validate, exceptions
def validated(validator, role: str = 'FUNC'):
def decorator(func: Callable):
@functools.wraps(func)
def wrapper(*args, **kwargs):
args_spec = inspect.getfullargspec(func)
instance = (args_spec.kwonlydefaults or {}).copy() # 取func定义的缺省值
instance.update(kwargs) # 使用实际的kw参数更新默认值(如果有的话)
if args_spec.args is not None: # 更新实际传入的args
instance.update({arg_name: args[index] for index, arg_name in enumerate(args_spec.args) if arg_name != 'self'})
schema = validator.get_schema(role=role)
schema['additionalProperties'] = True
try:
validate(instance, schema)
except exceptions.ValidationError as ex:
arg_name = ex.relative_path[-1]
raise ValueError('Parameter {0!r} - {1}'.format(arg_name, ex.message)) from None
else:
return func(*args, **kwargs)
return wrapper
return decorator
代码逻辑说明:
通过inspect获取函数的反射信息 尝试构造一个待审查的json实例instance 2.1 instance初始化为func的缺省参数(带参数值) 2.2 使用调用func时的实际关键字参数kwargs更新instance 2.3 如果func存在args,使用func中定义的{参数名:实际参数值}更新instance 从装饰器传入的validator(这里采用jsl包中的jsl.Document)取出校验schma 使用jsonschema.validate执行校验,成功的话执行原func,否则抛出首个不匹配的参数及错误详情来一个简单的使用代码示例:
# schema.py
...
class CreateAccountOfKeyPairSchema(Document):
app = StringField(required=True, pattern=r'^[^!#$%&*,]*$')
subject = StringField(required=True, pattern=r'^[^!#$%&*,]*$')
custom = StringField(required=True, pattern=r'^[^!#$%&*,]*$')
data = StringField(required=False)
...
# service.py
...
@validated(CreateAccountOfKeyPairSchema)
def create_account(self, app: str, subject: str, custom: str, data: str) -> str:
biz = TenAccountInfo()
biz.id = self._account_info_id_generator.next()
biz.app = app
biz.subject = subject
biz.custom = custom
biz.data = data
biz.invalid = 0
biz.version = self._version_generator.next()
ret = biz.id
self._account_info_dao.save(biz)
return ret
...
查看更多关于使用jsonschema通过装饰器优雅地对Python函数参数进行校验的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did126322