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 分支仍只读取序列化设置,使用其他正式版本时也应检查实际生成结果。


