DEBUG.WIKI
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →

Pydantic 能解码 base64,验证 Schema 却写成 binary

bytes 的 Schema 使用输出编码设置,输入验证却按另一项设置解码。先确认输入输出契约,再对称配置或仅修验证模式描述。

模型已经设置 val_json_bytes="base64",JSON 中的 "aGk=" 也能验证成 b"hi",但生成的验证 Schema 仍写着 format: binary。先比较输入解码与输出编码的配置,不要只改客户端发送内容。

Pydantic 2.14.1 的 bytes Schema 生成函数在验证和序列化两种模式里,都依据 ser_json_bytes 选择 format,而输入解码真正使用的是 val_json_bytes。两者不同,就可能出现“实际接受 base64,文档却描述另一种格式”,或相反的情况。

输入输出本来一致时,明确设置两边

接口约定输入和输出都采用 URL-safe base64 时,可以把配置写完整:

from pydantic import BaseModel, ConfigDict

class Payload(BaseModel):
    model_config = ConfigDict(
        val_json_bytes="base64",
        ser_json_bytes="base64",
    )
    data: bytes

validation_schema = Payload.model_json_schema(mode="validation")
serialization_schema = Payload.model_json_schema(mode="serialization")

这个约定下,二者的 data 字段应都描述为字符串、format: base64url。不仅要查看 Schema,还要核对真实输入解码后的字节,以及输出能否按约定还原;base64 配置对应 URL-safe 编码,不能仅凭一些 ASCII 样本就忽略编码字母表差异。

单向协议不要为了文档改掉输出

如果原接口有意接受 base64、输出 UTF-8,给 ser_json_bytes 也设为 base64 会改变返回值。这时应保留原来的输入输出规则,并为验证模式显式声明相符的 Schema,例如使用仅作用于验证模式的 WithJsonSchema。自定义 Schema 还应包含原来的长度等约束,不能用一个只剩 type、format 的片段覆盖掉既有要求。

同样,只有 ser_json_bytes="base64" 不会让输入自动按 base64 解码。字符串 "aGk=" 在 UTF-8 输入规则下可能保留为这几个字符的字节,而不是 b"hi"。能建立模型不代表实际解码符合协议。

修改前保存两种模式的 Schema 和代表性请求响应。若调整编码配置,接收方也要按同一个契约验收;撤回时一起恢复配置与文档,不能让代码已回到 UTF-8、生成客户端却仍发送 base64。2.14.1 的该 Schema 分支仍只读取序列化设置,使用其他正式版本时也应检查实际生成结果。