自定义 Schema
自定义 Schema¶
默认情况下,pyrs-yaml 使用 YAML 1.2 Core schema 进行隐式类型解析。通过 YAML Schema Language, 您可以定义自定义 schema,控制 plain scalar 如何解析为 Python 类型。
为何需要自定义 Schema?¶
Core schema 会将 0xFF 解析为 int(255),2026-08-11 解析为 int(2026),
hello 解析为 "hello"。有时您需要不同的行为:
- 将日期保留为字符串(
"2026-08-11"而非2026) - 将十六进制/二进制字面量解析为整数
- 添加 YAML 1.1 风格的布尔词法(
yes/no) - 使用纯 JSON 子集(不含
inf、nan、0x)
Schema 定义格式¶
Schema 定义为一个包含 rules 列表的 YAML 文件。每条规则包含一个 pattern(正则表达式)
和一个 type(null、bool、int、float、str 之一)。
# hex_schema.yaml
name: hex
extends: core
rules:
- pattern: ^0x[0-9a-fA-F]+$
type: int
- pattern: ^0b[01]+$
type: int
extends — 可选的基础 schema。规则优先匹配;若无匹配则回退到 extends 指定的 schema。
默认值:core。
rules — 有序列表。首个匹配的 pattern 决定类型。支持的类型:
type |
Python 结果 | 示例 |
|---|---|---|
null |
None |
~ |
bool |
True / False |
true, yes, on |
int |
int |
42, 0xFF, 0o77, 0b1010 |
float |
float |
3.14, 1e10 |
str |
str |
2026-08-11 |
注册和使用 Schema¶
注册并使用 schema
import pyrs_yaml
# 从 YAML 字符串注册
pyrs_yaml.register_schema(
"hex",
"""
name: hex
extends: core
rules:
- pattern: ^0x[0-9a-fA-F]+$
type: int
""",
)
# 使用 YAML 实例
y = pyrs_yaml.YAML(schema="hex")
doc = y.parse("addr: 0xFF")
assert doc.get("addr") == 255
# 使用模块级函数
d = pyrs_yaml.safe_load("addr: 0x1F", schema="hex")
assert d["addr"] == 31
从文件加载 schema¶
load_schema() 从文件路径读取 schema 定义并注册:
从文件加载 schema
# hex.yaml 包含上述 schema YAML
pyrs_yaml.load_schema("hex", "path/to/hex.yaml")
列出已注册 schema¶
list_schemas() 返回所有已注册的 schema 名称(内置 + 自定义):
列出已注册 schema
print(pyrs_yaml.list_schemas())
# ['failsafe', 'json', 'core', 'yaml1.1', 'hex', ...]
结构化校验¶
在 schema 定义中添加 validate 段,可在标量类型解析之上进行结构检查。使用 validate_against_schema() 在文档使用前校验:
带校验的 schema
name: app
extends: core
validate:
- path: $.port
type: int
required: true
- path: $.tags[*]
type: str
- path: $.numbers
sequence_of: int
- path: $.config
mapping_of: str
import pyrs_yaml
schema = """\
name: app
extends: core
validate:
- path: $.port
type: int
required: true
"""
pyrs_yaml.validate_against_schema("port: 80\n", schema) # OK
# 列出所有失败项并抛 YamlValidateError:
pyrs_yaml.validate_against_schema("port: abc\n", schema)
path— JSONPath 风格位置($.key、$.a.b、$.tags[*]);省略时应用于所有标量type— 标量必须解析为该 YAML 类型(null/bool/int/float/str)sequence_of/mapping_of— 每个元素 / 值必须为指定类型required— 路径必须存在且非 null(可与type组合)
内联 Dict Schema¶
无需预先注册,直接传入字典:
内联 dict schema
d = pyrs_yaml.safe_load(
"addr: 0xFF",
schema={
"extends": "core",
"rules": [{"pattern": "^0x[0-9a-fA-F]+$", "type": "int"}],
},
)
assert d["addr"] == 255
常见模式¶
schema = {
"extends": "core",
"rules": [{"pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "str"}],
}
schema = {
"extends": "core",
"rules": [{"pattern": "^(yes|no|Yes|No|YES|NO)$", "type": "bool"}],
}
schema = {
"extends": "failsafe",
"rules": [
{"pattern": "^null$|^~$", "type": "null"},
{"pattern": "^(true|false)$", "type": "bool"},
{"pattern": "^-?\\d+$", "type": "int"},
{"pattern": "^-?\\d+\\.\\d+$", "type": "float"},
],
}
性能¶
自定义 schema 使用基于正则表达式的规则引擎。每个 scalar 按顺序匹配规则。 为获得最佳性能:
- 规则数量控制在 20 条以内
- 将最常用的模式放在前面
- 使用
extends: core避免重复实现完整的 Core 解析逻辑
内置 Core schema 不受影响——它仍然使用零开销的 match 分发,不受自定义 schema 注册的影响。
另请参阅¶
- 插件开发 — 构建自定义标签处理器
- i18n 错误消息 — 为你的 schema 本地化错误消息
- Schema API 参考 —
register_schema()和内联 schema 文档