Zod logo

JSON Schema

💎

新功能 — Zod 4 引入了一项新功能:原生 JSON Schema 转换。JSON Schema 是描述 JSON 结构的标准(使用 JSON)。它广泛用于 OpenAPI 定义以及为 AI 定义 结构化输出

¥New — Zod 4 introduces a new feature: native JSON Schema conversion. JSON Schema is a standard for describing the structure of JSON (with JSON). It's widely used in OpenAPI definitions and defining structured outputs for AI.

要将 Zod 模式转换为 JSON 模式,请使用 z.toJSONSchema() 函数。

¥To convert a Zod schema to JSON Schema, use the z.toJSONSchema() function.

import { z } from "zod/v4";
 
const schema = z.object({
  name: z.string(),
  age: z.number(),
});
 
z.toJSONSchema(schema)
// => {
//   type: 'object',
//   properties: { name: { type: 'string' }, age: { type: 'number' } },
//   required: [ 'name', 'age' ]
// }

所有模式和检查都转换为最接近的 JSON 模式等效项。某些类型没有对应的类型,因此无法合理地表示。有关处理这些情况的更多信息,请参阅下面的 unrepresentable 部分。

¥All schema & checks are converted to their closest JSON Schema equivalent. Some types have no analog and cannot be reasonably represented. See the unrepresentable section below for more information on handling these cases.

z.bigint(); // ❌
z.int64(); // ❌
z.symbol(); // ❌
z.void(); // ❌
z.date(); // ❌
z.map(); // ❌
z.set(); // ❌
z.file(); // ❌
z.transform(); // ❌
z.nan(); // ❌
z.custom(); // ❌

字符串格式

¥String formats

Zod 将以下 Schema 类型转换为等效的 JSON Schema format

¥Zod converts the following schema types to the equivalent JSON Schema format:

// Supported via `format`
z.email(); // => { type: "string", format: "email" }
z.iso.datetime(); // => { type: "string", format: "date-time" }
z.iso.date(); // => { type: "string", format: "date" }
z.iso.time(); // => { type: "string", format: "time" }
z.iso.duration(); // => { type: "string", format: "duration" }
z.ipv4(); // => { type: "string", format: "ipv4" }
z.ipv6(); // => { type: "string", format: "ipv6" }
z.uuid(); // => { type: "string", format: "uuid" }
z.guid(); // => { type: "string", format: "uuid" }
z.url(); // => { type: "string", format: "uri" }

这些模式通过 contentEncoding 支持:

¥These schemas are supported via contentEncoding:

z.base64(); // => { type: "string", contentEncoding: "base64" }

所有其他字符串格式均通过 pattern 支持:

¥All other string formats are supported via pattern:

z.base64url();
z.cuid();
z.regex();
z.emoji();
z.nanoid();
z.cuid2();
z.ulid();
z.cidrv4();
z.cidrv6();

数字类型

¥Numeric types

Zod 将以下数字类型转换为 JSON Schema:

¥Zod converts the following numeric types to JSON Schema:

// number
z.number(); // => { type: "number" }
z.float32(); // => { type: "number", exclusiveMinimum: ..., exclusiveMaximum: ... }
z.float64(); // => { type: "number", exclusiveMinimum: ..., exclusiveMaximum: ... }
 
// integer
z.int(); // => { type: "integer" }
z.int32(); // => { type: "integer", exclusiveMinimum: ..., exclusiveMaximum: ... }

可空性

¥Nullability

Zod 将 JSON Schema 中的 undefined/null 转换为 { type: "null" }

¥Zod converts both undefined/null to { type: "null" } in JSON Schema.

z.null(); 
// => { type: "null" }
 
z.undefined(); 
// => { type: "null" }

同样,optionalnullable 通过 oneOf 变为可空:

¥Similarly, optional and nullable are made nullable via oneOf:

z.optional(z.string());
// => { oneOf: [{ type: "string" }, { type: "null" }] }
 
z.nullable(z.string());
// => { oneOf: [{ type: "string" }, { type: "null" }] }

配置

¥Configuration

第二个参数可用于自定义转换逻辑。

¥A second argument can be used to customize the conversion logic.

z.toJSONSchema(schema, {
  // ...params
})

以下是每个受支持参数的快速参考。下面将更详细地解释每个问题。

¥Below is a quick reference for each supported parameter. Each one is explained in more detail below.

interface ToJSONSchemaParams {
  /** The JSON Schema version to target.
 
   * - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
 
   * - `"draft-7"` — JSON Schema Draft 7 */
  target?: "draft-7" | "draft-2020-12";
 
  /** A registry used to look up metadata for each schema. 
 
   * Any schema with an `id` property will be extracted as a $def. */
  metadata?: $ZodRegistry<Record<string, any>>;
 
  /** How to handle unrepresentable types.
 
   * - `"throw"` — Default. Unrepresentable types throw an error
 
   * - `"any"` — Unrepresentable types become `{}` */
  unrepresentable?: "throw" | "any";
 
  /** How to handle cycles.
 
   * - `"ref"` — Default. Cycles will be broken using $defs
 
   * - `"throw"` — Cycles will throw an error if encountered */
  cycles?: "ref" | "throw";
 
  /* How to handle reused schemas.
 
   * - `"inline"` — Default. Reused schemas will be inlined
 
   * - `"ref"` — Reused schemas will be extracted as $defs */
  reused?: "ref" | "inline";
 
  /** A function used to convert `id` values to URIs to be used in *external* $refs.
 
   *    * Default is `(id) => id`.
   */
  uri?: (id: string) => string;
}

target

要设置目标 JSON 模式版本,请使用 target 参数。默认情况下,Zod 将以 2020-12 草案为目标。

¥To set the target JSON Schema version, use the target parameter. By default, Zod will target Draft 2020-12.

z.toJSONSchema(schema, { target: "draft-7" });
z.toJSONSchema(schema, { target: "draft-2020-12" });

metadata

如果你还没有阅读 元数据和注册表 页面,了解在 Zod 中存储元数据的上下文。

¥If you haven't already, read through the Metadata and registries page for context on storing metadata in Zod.

在 Zod 中,元数据存储在注册表中。Zod 导出一个全局注册表 z.globalRegistry,可用于存储常见的元数据字段,例如 idtitledescriptionexamples

¥In Zod, metadata is stored in registries. Zod exports a global registry z.globalRegistry that can be used to store common metadata fields like id, title, description, and examples.

import { z } from "zod/v4";
 
// `.meta()` is a convenience method for registering a schema in `z.globalRegistry`
const emailSchema = z.string().meta({ 
  title: "Email address",
  description: "Your email address",
});
 
z.toJSONSchema(emailSchema);
// => { type: "string", title: "Email address", description: "Your email address", ... } 

unrepresentable

以下 API 无法在 JSON Schema 中表示。默认情况下,如果遇到这些情况,Zod 会抛出错误。尝试转换为 JSON Schema 是不合理的;你应该修改你的模式,因为它们在 JSON 中没有等效的模式。如果遇到任何这些情况,都会抛出错误。

¥The following APIs are not representable in JSON Schema. By default, Zod will throw an error if they are encountered. It is unsound to attempt a conversion to JSON Schema; you should modify your schemas as they have no equivalent in JSON. An error will be thrown if any of these are encountered.

z.bigint(); // ❌
z.int64(); // ❌
z.symbol(); // ❌
z.void(); // ❌
z.date(); // ❌
z.map(); // ❌
z.set(); // ❌
z.file(); // ❌
z.transform(); // ❌
z.nan(); // ❌
z.custom(); // ❌

默认情况下,如果遇到任何这些情况,Zod 都会抛出错误。

¥By default, Zod will throw an error if any of these are encountered.

z.toJSONSchema(z.bigint());
// => throws Error

你可以通过将 unrepresentable 选项设置为 "any" 来更改此行为。这会将任何不可表示的类型转换为 {}(相当于 JSON Schema 中的 unknown)。

¥You can change this behavior by setting the unrepresentable option to "any". This will convert any unrepresentable types to {} (the equivalent of unknown in JSON Schema).

z.toJSONSchema(z.bigint(), { unrepresentable: "any" });
// => {}

cycles

如何处理循环。如果 z.toJSONSchema() 在遍历模式时遇到循环,它将使用 $ref 表示。

¥How to handle cycles. If a cycle is encountered as z.toJSONSchema() traverses the schema, it will be represented using $ref.

const User = z.object({
  name: z.string(),
  get friend() {
    return User;
  },
});
 
toJSONSchema(User);
// => {
//   type: 'object',
//   properties: { name: { type: 'string' }, friend: { '$ref': '#' } },
//   required: [ 'name', 'friend' ]
// }

如果你想抛出错误,请将 cycles 选项设置为 "throw"

¥If instead you want to throw an error, set the cycles option to "throw".

z.toJSONSchema(User, { cycles: "throw" });
// => throws Error

reused

如何处理在同一模式中多次出现的模式。默认情况下,Zod 将内联这些模式。

¥How to handle schemas that occur multiple times in the same schema. By default, Zod will inline these schemas.

const name = z.string();
const User = z.object({
  firstName: name,
  lastName: name,
});
 
z.toJSONSchema(User);
// => {
//   type: 'object',
//   properties: { 
//     firstName: { type: 'string' }, 
//     lastName: { type: 'string' } 
//   },
//   required: [ 'firstName', 'lastName' ]
// }

你可以将 reused 选项设置为 "ref",以将这些模式提取到 $defs 中。

¥Instead you can set the reused option to "ref" to extract these schemas into $defs.

z.toJSONSchema(User, { reused: "ref" });
// => {
//   type: 'object',
//   properties: {
//     firstName: { '$ref': '#/$defs/__schema0' },
//     lastName: { '$ref': '#/$defs/__schema0' }
//   },
//   required: [ 'firstName', 'lastName' ],
//   '$defs': { __schema0: { type: 'string' } }
// }

override

定义一些自定义覆盖逻辑,请使用 override。提供的回调可以访问原始 Zod 模式和默认 JSON 模式。此函数应直接修改 ctx.jsonSchema

¥To define some custom override logic, use override. The provided callback has access to the original Zod schema and the default JSON Schema. This function should directly modify ctx.jsonSchema.

const mySchema = /* ... */
z.toJSONSchema(mySchema, {
  override: (ctx)=>{
    ctx.zodSchema; // the original Zod schema
    ctx.jsonSchema; // the default JSON Schema
 
    // directly modify
    ctx.jsonSchema.whatever = "sup";
  }
});

请注意,在调用此函数之前,不可表示的类型将抛出 Error 错误。如果你尝试为不可表示的类型定义自定义行为,则需要同时设置 unrepresentable: "any"override

¥Note that unrepresentable types will throw an Error before this functions is called. If you are trying to define custom behavior for an unrepresentable type, you'll need to use set the unrepresentable: "any" alongside override.

// support z.date() as ISO datetime strings
const result = z.toJSONSchema(z.date(), {
  unrepresentable: "any",
  override: (ctx) => {
    const def = ctx.zodSchema._zod.def;
    if(def.type ==="date"){
      ctx.jsonSchema.type = "string";
      ctx.jsonSchema.format = "date-time";
    }
  },
});

io

某些模式类型具有不同的输入和输出类型,例如 ZodPipeZodDefault 和强制转换的原语。默认情况下,z.toJSONSchema 的结果代表输出类型;改用 "io": "input" 提取输入类型。

¥Some schema types have different input and output types, e.g. ZodPipe, ZodDefault, and coerced primitives. By default, the result of z.toJSONSchema represents the output type; use "io": "input" to extract the input type instead.

const mySchema = z.string().transform(val => val.length).pipe(z.number());
// ZodPipe
 
const jsonSchema = z.toJSONSchema(mySchema); 
// => { type: "number" }
 
const jsonSchema = z.toJSONSchema(mySchema, { io: "input" }); 
// => { type: "string" }

注册表

¥Registries

将模式传递给 z.toJSONSchema() 将返回一个独立的 JSON 模式。

¥Passing a schema into z.toJSONSchema() will return a self-contained JSON Schema.

在其他情况下,你可能有一组 Zod 模式,希望使用多个相互链接的 JSON 模式来表示,例如写入 .json 文件并通过 Web 服务器提供服务。为此,你可以将 registry 传递给 z.toJSONSchema()

¥In other cases, you may have a set of Zod schemas you'd like to represent using multiple interlinked JSON Schemas, perhaps to write to .json files and serve from a web server. To achieve this, you can pass a registry into z.toJSONSchema().

import { z } from "zod/v4";
 
const User = z.object({
  name: z.string(),
  get posts(){
    return z.array(Post);
  }
});
 
const Post = z.object({
  title: z.string(),
  content: z.string(),
  get author(){
    return User;
  }
});
 
z.globalRegistry.add(User, {id: "User"});
z.globalRegistry.add(Post, {id: "Post"});

上述 schema 均在 z.globalRegistry 中注册了 id 属性。要将这些转换为 JSON 模式,请将整个注册表传递给 z.toJSONSchema()

¥The schemas above both have an id property registered in z.globalRegistry. To convert these to JSON Schema, pass the entire registry into z.toJSONSchema().

z.toJSONSchema(z.globalRegistry);
// => {
//   schemas: {
//     User: {
//       id: 'User',
//       type: 'object',
//       properties: {
//         name: { type: 'string' },
//         posts: { type: 'array', items: { '$ref': 'Post' } }
//       },
//       required: [ 'name', 'posts' ]
//     },
//     Post: {
//       id: 'Post',
//       type: 'object',
//       properties: {
//         title: { type: 'string' },
//         content: { type: 'string' },
//         author: { '$ref': 'User' }
//       },
//       required: [ 'title', 'content', 'author' ]
//     }
//   }
// }

注册表中任何具有 id 属性的 Schema 都将被提取到 schemas 中。

¥Any schema with an id property in the registry will be extracted into schemas.

默认情况下,$ref URI 是相对路径,类似 "User"。要使这些属性成为绝对 URI,请使用 uri 选项。此示例需要一个将 id 转换为完全限定 URI 的函数。

¥By default, the $ref URIs are relative paths like "User". To make these absolute URIs, use the uri option. This expects a function that converts an id to a fully-qualified URI.

z.toJSONSchema(z.globalRegistry, {
  uri: (id) => `https://example.com/${id}.json`
});
// => {
//   schemas: {
//     User: {
//       id: 'User',
//       type: 'object',
//       properties: {
//         name: { type: 'string' },
//         posts: {
//           type: 'array',
//           items: { '$ref': 'https://example.com/Post.json' }
//         }
//       },
//       required: [ 'name', 'posts' ]
//     },
//     Post: {
//       id: 'Post',
//       type: 'object',
//       properties: {
//         title: { type: 'string' },
//         content: { type: 'string' },
//         author: { '$ref': 'https://example.com/User.json' }
//       },
//       required: [ 'title', 'content', 'author' ]
//     }
//   }
// }

On this page