
本文详解如何在 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-\x08\x0b\x0c\x0e-\x1f]*$') 等定制校验。
综上,Dict[str, JsonValue] 是表达「JSON 对象字典」语义最准确、最简洁且经官方验证的方案,兼顾类型安全性与运行时鲁棒性,是 Pydantic v2+ 中处理 JSON 数据结构的标准实践。










