如何用Pydantic处理含未知键、特殊字符键的JSON校验问题
最优解决方案(基于Pydantic V2主流版本)
核心思路
- 特殊键名用
Field(alias="")做别名映射,你计划将*映射为asterisk的方案完全可行 - 数量、名称不固定的动态键层,直接用
Dict[键校验规则, 值模型]结构定义,同时可附加键的格式校验规则 - 多层动态键的场景,每层按对应结构嵌套即可
完整实现代码示例
from pydantic import BaseModel, Field, Pattern from typing import Dict, Annotated # 1. 定义最内层通用属性模型 class InterfaceStatus(BaseModel): flag: str uptime: str class BunNode(BaseModel): flag: str join_time: str uptime: str # 2. 定义*对应的核心数据模型,用alias映射特殊键名 class AsteriskData(BaseModel): flag: str group1: str group_type: str uptime: str iif: Dict[str, InterfaceStatus] # iif下为动态接口名,用Dict承接 oil: Dict[str, BunNode] # oil下为动态bun名称,用Dict承接 address: str rp: str source: str upstream: str # 3. 定义外层动态键对应的包装模型 class OuterNode(BaseModel): asterisk: AsteriskData = Field(alias="*") # 将*键映射为asterisk字段 # 4. 定义顶层模型,校验顶层键的命名规范 # 用正则限制顶层键必须为数字_数字_数字_数字格式 DynamicKey = Annotated[str, Pattern(r"^\d+_\d+_\d+_\d+$")] class RootModel(BaseModel): __root__: Dict[DynamicKey, OuterNode] # __root__表示整个模型为对应Dict结构
使用方式
import json # 加载目标JSON数据 with open("data.json", "r", encoding="utf-8") as f: raw_data = json.load(f) # 执行校验 result = RootModel.model_validate(raw_data) # 数据访问示例 # 遍历所有顶层动态键 for key, outer_node in result.__root__.items(): print(f"顶层键: {key}") # 直接通过asterisk字段访问原*对应的数据 core_data = outer_node.asterisk print(f"组地址: {core_data.group1}") # 遍历oil下的所有bun节点 for bun_name, bun_data in core_data.oil.items(): print(f"bun名称: {bun_name}, 上线时间: {bun_data.uptime}") # 输出JSON时要保留原*键,添加by_alias参数即可 print(result.model_dump_json(by_alias=True, indent=2))
补充说明
如果使用Pydantic V1版本,仅需做两处调整:将model_validate替换为parse_obj,model_dump_json替换为json,其余逻辑完全兼容。
内容的提问来源于stack exchange,提问作者RaamEE
相关产品推荐
相关产品推荐

