
本文详解如何在 Pydantic 中精准定义和验证符合 jsON 序列化规范的嵌套字典结构(即 Dict[str, jsonValue]),避免递归类型错误,确保字段值仅包含 JSON 原生可序列化类型(str/int/Float/bool/None/List/Dict)。
本文详解如何在 pydantic 中精准定义和验证符合 json 序列化规范的嵌套字典结构(即 `dict[str, jsonvalue]`),避免递归类型错误,确保字段值仅包含 json 原生可序列化类型(str/int/float/bool/none/list/dict)。
在构建 API 请求体、配置解析或数据清洗场景中,我们常需严格约束某个字段为「合法的 JSON 值」——它必须能被 json.dumps() 无异常地序列化,即仅允许 JSON 原生支持的类型:字符串、数字(int/float)、布尔值、NULL(对应 Python 的 None)、列表(元素也需 JSON 兼容)和字典(键必须为 str,值也需 JSON 兼容)。此时,简单使用 Dict[str, Any] 过于宽泛(如允许 datetime、set、自定义类等非 JSON 类型),而 pydantic.Json 又仅用于校验 JSON 字符串 的解析结果,均不满足需求。
Pydantic v2+ 提供了开箱即用的类型别名 JsonValue,专为此类场景设计。它是一个前向引用的递归联合类型,定义如下:
from pydantic.types import JsonValue # ✅ 推荐导入方式(Pydantic >= 2.6) # 或从旧路径(兼容早期 v2.x): # from pydantic import JsonValue # 等价于(无需手动定义,避免 RecursionError): # JsonValue = union[ # List["JsonValue"], # Dict[str, "JsonValue"], # str, # bool, # int, # float, # None, # ]
若目标是校验一个JSON 对象(即字典),应直接使用 Dict[str, JsonValue] —— 它确保键为字符串,且所有值(包括嵌套的任意层级)均为 JSON 可序列化类型:
from typing import Dict, List from pydantic import BaseModel, ValidationError from pydantic.types import JsonValue class ConfigModel(BaseModel): metadata: Dict[str, JsonValue] # ✅ 正确:JSON 兼容的字典 tags: List[JsonValue] # ✅ 同样适用于列表 # ✅ 合法输入(全部可被 json.dumps() 处理) valid_data = { "metadata": { "name": "app", "version": 1.2, "active": True, "features": ["auth", "logging"], "settings": {"timeout": 30, "retry": None} }, "tags": ["prod", 42, False, None] } model = ConfigModel(**valid_data) # ❌ 触发 ValidationError:datetime 不在 JsonValue 范围内 invalid_data = {"metadata": {"created_at": datetime.now()}} try: ConfigModel(**invalid_data) except ValidationError as e: print(e) # > 1 validation error for ConfigModel # > metadata -> created_at # > Input should be a valid string, number, boolean, None, list or dict [type=union_tag_invalid, input_value=datetime.datetime(...), input_type=datetime]
⚠️ 关键注意事项:
- JsonValue 是 运行时类型提示,Pydantic 在实例化时执行深度验证(包括嵌套结构),而非仅做静态类型检查;
- 不要尝试手动重新定义 JsonValue(如 Union[Dict[str, ‘JsonValue’], …]),会导致 RecursionError —— Pydantic 已通过内部机制安全处理前向引用;
- 若需接收 JSON 字符串并自动解析为 JsonValue 结构,应使用 Json[JsonValue](注意:Json[T] 表示“传入字符串,解析后验证为 T”);
- JsonValue 不校验键名是否为合法 JSON 字符串(如含控制字符),但实际 JSON 序列化器(如 json.dumps)会拒绝此类键;Pydantic 默认接受,如需额外约束,可配合 Field(pattern=r’^[^x00-x08x0bx0cx0e-x1f]*$’) 等定制校验。
综上,Dict[str, JsonValue] 是表达「JSON 对象字典」语义最准确、最简洁且经官方验证的方案,兼顾类型安全性与运行时鲁棒性,是 Pydantic v2+ 中处理 JSON 数据结构的标准实践。