Cerberus能否校验嵌套递归结构?如何编写递归校验Schema?
递归Schema实现树形节点结构校验
当然可以用递归Schema完成这项校验,下面以Python生态中常用的两种方案为例,给出具体实现:
方案1:使用Pydantic(类型友好,推荐)
Pydantic支持自引用模型定义,天然适配递归树形结构的校验需求:
步骤1:定义递归节点模型
先明确每个节点的字段规则(比如cap要求为整数,可根据实际需求调整),通过自引用定义children字段:
from pydantic import BaseModel, ValidationError from typing import List, Optional class Node(BaseModel): cap: int # 明确cap的类型,这里要求为整数 node_id: str # 假设每个节点必须有唯一标识 children: Optional[List["Node"]] = None # 递归引用自身模型 # 解决自引用的前置声明问题 Node.update_forward_refs()
步骤2:执行校验
将响应数据传入模型实例化,Pydantic会自动递归遍历所有子节点,校验每个字段的结构:
# 示例响应数据(包含错误的child-112节点) resp = { "node_id": "root", "cap": 100, "children": [ {"node_id": "child-111", "cap": 50, "children": None}, {"node_id": "child-112", "cap": "50", "children": []} # cap为字符串,不符合规则 ] } try: validated_data = Node(**resp) print("所有节点结构校验通过") except ValidationError as e: # 错误信息会精准定位到问题节点,比如child-112的cap字段类型错误 print(f"校验失败:{e}")
运行后会得到类似如下的错误提示,直接指出问题位置:
校验失败:1 validation error for Node children.1.cap Input should be a valid integer, got a string [type=int_type, input_value='50', input_type=str]
方案2:使用JSON Schema(跨语言通用)
如果需要跨语言或更通用的校验规则,可以用JSON Schema的递归引用特性:
步骤1:定义递归Schema
通过$ref关键字引用自身,实现递归校验:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "cap": {"type": "integer"}, "node_id": {"type": "string"}, "children": { "type": "array", "items": {"$ref": "#"} # 递归引用当前Schema } }, "required": ["cap", "node_id"], "additionalProperties": false }
步骤2:执行校验
用jsonschema库加载Schema并校验数据:
import jsonschema # 加载上面的Schema schema = { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "cap": {"type": "integer"}, "node_id": {"type": "string"}, "children": {"type": "array", "items": {"$ref": "#"}} }, "required": ["cap", "node_id"], "additionalProperties": false } try: jsonschema.validate(instance=resp, schema=schema) print("所有节点结构校验通过") except jsonschema.exceptions.ValidationError as e: print(f"校验失败:{e}")
核心逻辑说明
两种方案的核心都是让子节点的校验规则引用根节点的规则,从而实现自动递归遍历所有层级的节点,只要任意一个子节点的字段不符合定义,就会抛出明确的错误信息,帮你快速定位问题节点(比如你提到的child-112)。
内容的提问来源于stack exchange,提问作者Lezakk
相关产品推荐
相关产品推荐

