简单,快速,可拓展的数据校验库。
- 比JSON Schema更简洁,可读性更好的Schema
- 拥有标准库中 json.loads 20%~40% 的速度
- 能够序列化任意类型对象
- 实现自定义校验器非常容易
- 准确的错误提示,包括错误原因和位置
注意:仅支持 python 3.3+
pip install validater
>>> from validater import SchemaParser,Invalid
>>> sp = SchemaParser()
>>> f = sp.parse("int(0, 9)")
>>> f("3")
3
>>> f(-1)
...
validater.exceptions.Invalid: value must >= 0
>>> f("abc")
...
validater.exceptions.Invalid: invalid int
>>>>>> f = sp.parse({"userid?int(0,9)": "UserID"})
>>> user = {"userid": 15}
>>> f(user)
...
validater.exceptions.Invalid: value must 9 in userid
>>> class User:pass
...
>>> user = User()
>>> user.userid=5
>>> f(user)
{'userid': 5}
>>> user.userid = 15
>>> f(user)
...
validater.exceptions.Invalid: value must 9 in userid
>>> f = sp.parse({"friends":[{"userid?int(0,9)":"UserID"}]})
>>> f({"friends":[user,user]})
...
validater.exceptions.Invalid: value must 9 in friends[0].userid
>>> user.userid=5
>>> f({"friends":[user,user]})
{'friends': [{'userid': 5}, {'userid': 5}]}
>>>>>> user.userid = 15
>>> try:
f({"friends":[user,user]})
except Invalid as ex:
print(ex.message)
print(ex.position)
>>>
value must 9
friends[0].userid
>>>简单用法:
>>> shared = {"userid": "int(0,9)"}
>>> sp = SchemaParser(shared=shared)
>>> f = sp.parse("@userid")
>>> f(5)
5
>>> f = sp.parse({"userid@userid":"UserID"})
>>> f({"userid":5})
{'userid': 5}
>>> f = sp.parse(["@userid"])
>>> f([1,2])
[1, 2]
>>> f = sp.parse({"userid@userid&optional":"UserID"})
>>> f({"userid":None})
{'userid': None}
>>>引用内部相互引用:
>>> from collections import OrderedDict
>>> shared = OrderedDict([
("userid", "int(0,9)"),
("user", {"userid@userid":"UserID"}),
])
>>> sp = SchemaParser(shared=shared)
>>> f = sp.parse("@user")
>>> f({"userid":5})
{'userid': 5}注意:只能后面的引用前面的,并且要使用OrderedDict代替dict。
>>> shared = OrderedDict([
("user", {"userid@userid":"UserID"}),
("userid", "int(0,9)"),
])
>>> sp = SchemaParser(shared=shared)
...
validater.exceptions.SchemaError: shared 'userid' not found in user.userid>>> shared = {
"size": {
"width?int": "width",
"height?int": "height"
},
"border": {
"border-width?int": "border-width",
"border-style?str": "border-style",
"border-color?str": "border-color"
}
}
>>> sp = SchemaParser(shared=shared)
>>> f = sp.parse({"$self@size@border": "mixins"})
>>> value = {
"width": "400",
"height": "400",
"border-width": "5",
"border-style": "solid",
"border-color": "red"
}
>>> f(value)
{'height': 400, 'border-width': 5, 'border-color': 'red', 'border-style': 'solid', 'width': 400}
>>>注意:只有字典结构的Schema才能混合,非字典结构的Schema混合会在校验数据时抛出SchemaError。 另外,不要混合有相同key的Schema。
handle_default_optional_desc 装饰器能让自定义的validater支持 default, optional, desc 这几个参数。
>>> from validater.validaters import handle_default_optional_desc
>>> @handle_default_optional_desc()
... def multiple_validater(n):
... def validater(value):
... if value%n==0:
... return value
... else:
... raise Invalid("不是 %d 的倍数"%n)
... return validater
...
>>> validaters={"multiple":multiple_validater}
>>> sp = SchemaParser(validaters=validaters)
>>> f = sp.parse("multiple(3)")
>>> f(6)
6
>>> f(5)
...
validater.exceptions.Invalid: 不是 3 的倍数
>>> f = sp.parse("multiple(3)&default=3")
>>> f(None)
3
>>>字符串类型的校验器请用 @handle_default_optional_desc(string=True) 装饰器,这样会将空字符串视为null,更符合default和optional的语义。
>>> from validater.validaters import build_re_validater
>>> regex_time = r'([01]?\d|2[0-3]):[0-5]?\d:[0-5]?\d'
>>> time_validater = build_re_validater("time", regex_time)
>>> sp = SchemaParser(validaters={"time":time_validater})
>>> f = sp.parse('time&default="00:00:00"')
>>> f("12:00:00")
'12:00:00'
>>> f("12:00:00123")
...
validater.exceptions.Invalid: invalid time
>>> f(None)
'00:00:00'
>>>内置的idcard校验函数只校验数字长度和xX,不校验地址码和日期。
支持 +86 开头,支持校验手机号段,只支持11位手机号,不支持固定电话号码。
见Schema语法。
用tox测试:
pip install tox
tox
用pytest测试:
pip install pytest
py.test
# benchmark
python benchmark.py
# profile
python benchmark.py -p
validater是拼写错误的单词,正确的拼写是validator,但是validator这个名字已经被用掉了,所以继续用validater这个名字。
MIT License