编解码器
✨ 新特性 — zod@4.1 中新增
所有 Zod 模式(schema)都支持正向和反向两种输入处理方式:
- 正向:
Input到Output.parse().decode()
- 反向:
Output到Input.encode()
在大多数情况下,这种区分没有区别。输入类型和输出类型是相同的,所以“正向”和“反向”没有差异。
然而,某些模式类型会导致输入类型和输出类型不一致,尤其是 z.codec()。编码器是一种特殊的模式(schema),定义了两个其他模式之间的双向转换。
在这些情况下,z.decode() 和 z.encode() 的行为截然不同。
注意 — 这里的“方向”和术语没有特别含义。使用 A -> B 编解码器进行编码,也可以用 B -> A 编解码器进行解码。这里的“decode”和“encode”只是约定俗成的用语。
这对在网络边界处理数据特别有用。你可以在客户端和服务器间共享单个 Zod 模式,并用它在网络友好格式(如 JSON)和 JavaScript 丰富数据表示之间做转换。
组合性
注意 — 你可以对任何模式使用 z.encode() 和 z.decode(),不必非得是 ZodCodec。
编解码器和普通模式一样。它们可以嵌套在对象、数组、管道等结构中,使用没有任何限制!
类型安全的输入
.parse() 和 .decode() 在运行时行为一致,但它们的类型签名不同。.parse() 方法接受 unknown 类型输入,返回符合模式推断的输出类型的值。相比之下,z.decode() 和 z.encode() 函数的输入是强类型的。
为什么有区别?编码和解码意味着转换。在很多场景中,这些方法的输入在应用代码里已经是强类型,因此 z.decode 和 z.encode 接受强类型输入以便在编译时发现错误。
下面的示意图展示了 parse()、decode() 和 encode() 的类型签名差异。


异步和安全版本
和 .transform() 及 .refine() 一样,编解码器支持异步转换。
和普通的 parse() 一样,decode() 和 encode() 有“安全”及异步版本。
编码机制详解
某些 Zod 模式“反转”其解析行为存在细微差别。
编解码器(Codecs)
这个比较直观。编解码器封装了两个类型之间的双向转换。z.decode() 会触发 decode 转换,将输入转换为解析后的值,而 z.encode() 则触发 encode 转换,序列化回去。
管道(Pipes)
趣闻 — 编解码器实际上是内部基于管道(pipe)的子类,并添加了“中间”转换逻辑。
在普通解码时,ZodPipe<A, B> 模式先用 A 解析数据,再传给 B。编码时,数据先用 B 编码,再传回 A。
约束(Refinements)
所有验证检查(.refine()、.min()、.max() 等)在两种方向都会执行。
为了避免自定义 .refine() 逻辑在 z.encode() 中抛出意外错误,Zod 会进行两遍“检测”。第一遍确保输入符合期望类型(避免出现 invalid_type),通过后才会进行第二遍执行约束逻辑。
这种设计也支持“变异转换”(mutating transforms),比如 z.string().trim() 或 z.string().toLowerCase():
默认值和前置默认值
默认值和前置默认值仅应用于“正向”方向。
当你给模式附加默认值时,输入变成可选(| undefined),但输出不变。因此,undefined 不是 z.encode() 的有效输入,默认值不会生效。
捕获(Catch)
同样地,.catch() 仅在“正向”方向生效。
Stringbool
注意 — Stringbool 早于 Zod 引入编解码器。现在它内部已重写为编解码器实现。
z.stringbool() API 将字符串值(如 "true"、"false"、"yes"、"no" 等)转换成 boolean。默认情况下,z.encode() 会将 true 转成 "true",将 false 转成 "false"。
如果你指定了自定义的 truthy 和 falsy 数组,则数组的第一个元素会被用作编码结果。
转换(Transforms)
⚠️ — .transform() API 实现的是单向转换。如果你的某个模式包含 .transform(),调用 z.encode() 会发生运行时错误(非 ZodError)。
有用的编解码器
下面是常用编解码器的实现示例。为便于定制,这些并未作为 Zod 的一等 API 直接提供。你应复制粘贴进项目中,根据需要修改。
注意 — 所有下列编解码器实现均经过正确性测试。
stringToNumber
使用 parseFloat() 将数字字符串转换为 JavaScript number 类型。
stringToInt
使用 parseInt() 将整数字符串转换为 JavaScript 的 number 类型。
stringToBigInt
将字符串转换为 JavaScript 的 bigint 类型。
numberToBigInt
将 JavaScript 的 number 转换为 bigint 类型。
isoDatetimeToDate
将 ISO 日期时间字符串转换为 JavaScript Date 对象。
epochSecondsToDate
将 Unix 时间戳(秒)转换为 JavaScript Date 对象。
epochMillisToDate
将 Unix 时间戳(毫秒)转换为 JavaScript Date 对象。
json(schema)
将 JSON 字符串解析为结构化数据,并序列化回 JSON。该泛型函数接受一个输出模式用于验证解析后的 JSON。
使用示例:
utf8ToBytes
将 UTF-8 字符串转换为 Uint8Array 字节数组。
bytesToUtf8
将 Uint8Array 字节数组转换为 UTF-8 字符串。
base64ToBytes
将 Base64 字符串转换为 Uint8Array 字节数组,反之亦然。
base64urlToBytes
将 Base64url 字符串(URL安全的 Base64)转换为 Uint8Array 字节数组。
hexToBytes
将十六进制字符串转换为 Uint8Array 字节数组,反之亦然。
stringToURL
将 URL 字符串转换为 JavaScript URL 对象。
stringToHttpURL
将 HTTP/HTTPS URL 字符串转换为 JavaScript URL 对象。
uriComponent
使用 encodeURIComponent() 和 decodeURIComponent() 编码和解码 URI 组件。

