-
Notifications
You must be signed in to change notification settings - Fork 12
Schema 语法
kk edited this page Jun 29, 2018
·
1 revision
本质上,所有数据都可以用函数来描述。
比如,一个大于 0 的整数:
def validate_int_plus(value):
assert isinstance(value, int), 'invalid number'
assert value > 0, 'number must > 0'
又如,一个最大长度为 120 个字符的字符串:
def validate_str_maxlen_120(value):
assert isinstance(value, str), 'invalid string'
assert len(value) <= 120, 'string too long'
把这些函数分门别类,就有了各种 校验器。
比如,可以指定最大值和最小值的整数校验器:
def int_validator(min, max):
def validate(value):
assert isinstance(value, int), 'invalid number'
assert value >= min, f'number must >= {min}'
assert value <= max, f'number must <= {max}'
return validate
Schema 仅仅是校验器的一种表示方式。
经过对比,我发现一种 渐进表示法 非常适合。
比如,整数校验器:
int
最小值为 0 的整数校验器:
int.min(0)
最小值为 0,最大值为 100 的整数校验器:
int.min(0).max(100)
它可以根据需要,不断地补充描述。
另外,如果参数值为 True
,可以省略参数值:
int.optional(True) == int.optional
对于字典和列表,可以校验容器內的元素:
list( int.min(0).max(100) )
dict(
key1=int.min(0).max(100),
key2=str.maxlen(10),
)
因为 int, str, dict 等等在 Python 中已有特定的含义,
所以要给校验器名称加上 T.
前缀,例如:
T.int.min(0).max(100)
T.dict(
key1=T.int.min(0).max(100),
key2=T.str.maxlen(10),
)
也可以用 Python 类定义 Dict Schema:
@modelclass
class MyModel:
key1 = T.int.min(0).max(100)
key2 = T.str.maxlen(10)
JSON 数据可以分为3种结构:
- 映射:"名称/值"对的集合,也被理解为对象(object)或字典(dictionary)
- 序列:有序列表,也被理解为数组
- 标量:string number true false null
Schema 本身也是 JSON,也用这三种结构描述相应的数据,也因此称为 同构的JSON-Schema。
映射结构用 $self 描述自身,其余 key 描述字典里的内容:
{
"$self": "schema",
"key": "schema"
}
序列结构用第一个元素描述自身,第二个元素描述序列里的内容:
["schema", Item]
序列结构也可以省略第一个元素,即只描述序列里的内容,不描述自身。
[Item]
标量结构用字符串描述自身:
"schema"
注:JSON 格式主要用于跨语言使用 Schema。
这是实际数据:
{
"id": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"]
}
对应 Schema 的 Python 语法表示:
T.dict(
id=T.int.desc('The unique identifier for a product'),
name=T.str.desc('Name of the product'),
price=T.float.exmin(0),
tags=T.list(
T.str.minlen(1)
).unique
)
用 Python 类定义的 Schema:
@modelclass
class Product:
id = T.int.desc('The unique identifier for a product')
name = T.str.desc('Name of the product')
price = T.float.exmin(0)
tags = T.list(
T.str.minlen(1)
).unique
对应 Schema 的 JSON 语法表示:
{
"$self": "dict",
"id": "int.desc('The unique identifier for a product')",
"name": "str.desc('Name of the product')",
"price": "float.exmin(0)",
"tags": [
"list.unique",
"str.minlen(1)"
]
}