如何让Pydantic识别YAML映射中冒号后无空格的属性违规?
解决Pydantic无法识别YAML格式错误的问题
问题根源
你的代码中断言失败,是因为YAML流映射({}包裹的结构)里的walk:True没有在冒号后加空格,被PyYAML解析成了一个名为walk:True的额外字段(值为None),而非walk字段对应布尔值True。由于Pydantic默认会忽略模型中未定义的字段,所以path_cls的walk属性保持默认值False,导致断言失败。
解决方案
方案1:让Pydantic拒绝额外字段
给Pydantic模型添加extra = Extra.forbid配置,这样当解析结果中出现模型未定义的字段时,直接抛出验证错误,就能立刻发现这类YAML格式问题。
修改后的代码:
import yaml from pydantic import BaseModel, parse_obj_as, Extra from typing import List class path_cls(BaseModel): path : str walk : bool = False other : bool = False class Config: extra = Extra.forbid # 禁止额外字段 class myschema(BaseModel): paths: List[path_cls] ydata = yaml.safe_load(""" --- paths: - {path: .., walk:True } - {path: ../../somefolder } """) data = parse_obj_as(myschema, ydata) assert data.paths[0].walk
此时运行代码会直接抛出ValidationError,提示存在未识别的字段walk:True,快速定位问题。
方案2:在YAML解析阶段严格校验格式
如果需要从根源上避免这种格式错误,可以自定义PyYAML的Loader,在解析流映射时检查每个键值对是否符合键: 值(冒号后必须有空格)的格式,不符合则抛出解析错误。
示例代码:
import yaml from yaml.parser import Parser from yaml.scanner import Scanner from pydantic import BaseModel, parse_obj_as, Extra from typing import List class StrictFlowLoader(Scanner, Parser): def fetch_flow_mapping_value(self): # 检查冒号后是否有空格 if self.peek() != ' ': raise yaml.YAMLError(f"Flow mapping中键值对格式错误:冒号后必须加空格,当前位置:{self.get_mark()}") super().fetch_flow_mapping_value() class path_cls(BaseModel): path : str walk : bool = False other : bool = False class Config: extra = Extra.forbid class myschema(BaseModel): paths: List[path_cls] # 使用自定义Loader解析YAML ydata = yaml.load(""" --- paths: - {path: .., walk:True } - {path: ../../somefolder } """, Loader=StrictFlowLoader) data = parse_obj_as(myschema, ydata) assert data.paths[0].walk
这样在解析YAML时就会直接报错,提前拦截格式问题。
通用方案
对于所有需要严格校验的场景,推荐:
- 全局或给所有模型配置
extra = Extra.forbid,拒绝任何未定义的字段,防止因格式错误产生的无效字段被忽略。 - 结合自定义YAML Loader,对格式做更严格的校验,从解析阶段就杜绝不符合规范的写法。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

