JSON 转 Python 数据模型
把 JSON 生成 Pydantic BaseModel 类,自动推断 int、str 等类型,嵌套对象拆成独立模型。
用请求库拿到 JSON 后直接按字典下标取值,字段名拼错、层级判断错都要等到运行时才报错,接口字段一改名更是全项目排查。把样例 JSON 转成 Pydantic 模型后,字段名和类型在代码里是显式的,取值有校验、编辑器有补全,字段缺失会在校验阶段抛出明确错误,而不是在下游某处变成一个 None。
转换在浏览器本地进行,JSON 内容和生成的模型都不会上传。生成的模型只描述结构,不给默认值也不加 alias,因此所有字段默认必填;拿到可能缺字段的第三方数据时,需要自己补默认值和可选类型,这一点在下面的说明里会具体讲。
生成的模型结构
每个对象生成一个继承 BaseModel 的类,空对象生成 pass 占位。嵌套模型在输出里排在父模型之前,因此不需要写前向引用或引入延迟注解就能直接运行。文件头部固定输出 typing 的 List、Any 和 pydantic 的 BaseModel 两行 import。字段注解用的是 typing.List 的写法而不是内置泛型 list,这个写法在 Pydantic v1 和 v2 下都能正常校验,不必为了升级而改写模型定义。
必填字段与版本差异
生成器不给任何字段默认值,所以所有字段在 Pydantic 里都是必填,接口少返回一个字段就会抛校验错误;对接可能缺字段的第三方数据时,要自己加上等于 None 的默认值。另外 v1 用 dict、parse_obj、内部 Config 类和 validator,v2 换成了 model_dump、model_validate、model_config 和 field_validator,方法名不兼容。只做模型定义时两种写法都能跑,但升级到 v2 后这些调用点必须逐个替换。
键名与类型陷阱
字段名直接沿用 JSON 的键,不做驼峰转下划线,也没有 alias 设置,所以驼峰键会原样成为字段名,在 Python 里能跑但不符惯例。键名含连字符或点号时生成的代码是语法错误,class、from 这类 Python 关键字做键名同样直接报错,这些情况需要手工改成下划线名并补上别名映射。类型上,null 生成 Any 而不是可选类型且字段依然必填,空数组生成 List[Any],数组只看第一个元素,超过 15 位有效数字的整数和小数在解析阶段就已被双精度浮点截断。
常见问题
- 生成的代码在 Pydantic v2 上能直接用吗?
- 能。模型定义方式,包括继承 BaseModel、typing.List 注解和 Any,在 v1 与 v2 下都合法。不兼容的是调用侧:v2 用 model_dump、model_validate、model_config 和 field_validator,替换掉 v1 的 dict、parse_obj、Config 与 validator 即可。
- 为什么所有字段都没有默认值?
- 生成器只按 JSON 的静态结构推断类型,不判断某个字段是否可能缺失,所以不生成默认值,Pydantic 会把这些字段视为必填,缺字段直接抛校验错误。要给可缺省字段加默认值,手工补上等于 None,同时把类型改成可选,否则传 None 依然校验失败。
- 为什么 null 生成 Any 而不是可选类型?
- 因为无法判断它是稳定的 null 还是偶尔为 null 的其它类型,退回 Any 至少不会校验失败。代价是没有类型约束,需要严格约束时把该字段改成 Optional 加具体类型或使用竖线联合写法,并给它默认值 None,这样缺字段和显式 null 都能通过。
- 嵌套对象会生成独立的类吗?定义顺序有问题吗?
- 会,每个嵌套对象生成独立的 BaseModel 子类,并且子模型在输出里排在父模型前面,所以直接运行不会遇到类未定义的前向引用问题。同名嵌套对象只生成一次,先出现者生效,结构不同的两个同名分支需要手工重命名后再使用。