💎 Zod 4 is now stable!  Read the announcement.
Zod logo

JSON Schema

💎

新機能 — Zod 4 は、ネイティブの JSON Schema 変換という新機能を導入しました。JSON Schema は、JSON の構造(JSON を使用)を記述するための標準です。OpenAPI 定義や AI の 構造化出力 の定義で広く使用されています。

Zod スキーマを JSON Schema に変換するには、z.toJSONSchema() 関数を使用します。

import * as z from "zod";
 
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' ],
//   additionalProperties: false,
// }

すべてのスキーマとチェックは、最も近い JSON Schema の同等物に変換されます。一部のタイプには類似物がなく、合理的に表現できません。これらのケースの処理の詳細については、以下の unrepresentable セクションを参照してください。

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

文字列フォーマット (String formats)

Zod は、次のスキーマタイプを同等の 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 を介してサポートされています。

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

他のすべての文字列フォーマットは pattern を介してサポートされています。

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

数値型 (Numeric types)

Zod は、次の数値型を 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: ... }

オブジェクトスキーマ (Object schemas)

デフォルトでは、z.object() スキーマには additionalProperties: "false" が含まれています。これは Zod のデフォルト動作の正確な表現であり、プレーンな z.object() スキーマは追加のプロパティを取り除くためです。

import * as z from "zod";
 
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' ],
//   additionalProperties: false,
// }

"input" モードで JSON Schema に変換する場合、additionalProperties は設定されません。詳細については、io ドキュメント を参照してください。

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

対照的に:

  • z.looseObject()決して additionalProperties: false を設定しません
  • z.strictObject()常に additionalProperties: false を設定します

ファイルスキーマ (File schemas)

Zod は z.file() を次の OpenAPI フレンドリーなスキーマに変換します。

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

サイズと MIME のチェックも表現されます。

z.file().min(1).max(1024 * 1024).mime("image/png");
// => {
//   type: "string",
//   format: "binary",
//   contentEncoding: "binary",
//   contentMediaType: "image/png",
//   minLength: 1,
//   maxLength: 1048576,
// }

ヌル可能性 (Nullability)

Zod は z.null() を JSON Schema での { type: "null" } に変換します。

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

z.undefined() は JSON Schema では表現できないことに注意してください(下記 を参照)。

同様に、nullablenull との和集合を介して表現されます。

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

オプションのスキーマはそのまま表現されますが、optional アノテーションで装飾されます。

z.optional(z.string());
// => { type: "string" }

設定 (Configuration)

2番目の引数を使用して、変換ロジックをカスタマイズできます。

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

以下は、サポートされている各パラメータのクイックリファレンスです。それぞれについては、以下で詳しく説明します。

interface ToJSONSchemaParams {
  /** The JSON Schema version to target.
   * - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
   * - `"draft-7"` — JSON Schema Draft 7
   * - `"draft-4"` — JSON Schema Draft 4
   * - `"openapi-3.0"` — OpenAPI 3.0 Schema Object */
  target?: "draft-4" | "draft-7" | "draft-2020-12" | "openapi-3.0";
 
  /** 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 Schema バージョンを設定するには、target パラメータを使用します。デフォルトでは、Zod は Draft 2020-12 をターゲットにします。

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

metadata

まだ読んでいない場合は、Zod でのメタデータの保存に関するコンテキストについて メタデータとレジストリ ページを参照してください。

Zod では、メタデータはレジストリに保存されます。Zod は、idtitledescriptionexamples などの一般的なメタデータフィールドを保存するために使用できるグローバルレジストリ z.globalRegistry をエクスポートします。

import * as z from "zod";
 
// `.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", ... } 

すべてのメタデータフィールドは、生成される JSON Schema にコピーされます。

const schema = z.string().meta({
  whatever: 1234
});
 
z.toJSONSchema(schema);
// => { type: "string", whatever: 1234 }

unrepresentable

次の API は JSON Schema では表現できません。デフォルトでは、Zod はこれらに遭遇するとエラーをスローします。JSON Schema への変換を試みるのは不健全です。JSON には同等のものがないため、スキーマを変更する必要があります。これらに遭遇するとエラーがスローされます。

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

デフォルトでは、Zod はこれらに遭遇するとエラーをスローします。

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

unrepresentable オプションを "any" に設定することで、この動作を変更できます。これにより、表現不可能なタイプは {}(JSON Schema の unknown に相当)に変換されます。

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

cycles

循環の処理方法。z.toJSONSchema() がスキーマをトラバースする際に循環が検出された場合、$ref を使用して表現されます。

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

代わりにエラーをスローしたい場合は、cycles オプションを "throw" に設定します。

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

reused

同じスキーマ内で複数回発生するスキーマの処理方法。デフォルトでは、Zod はこれらのスキーマをインライン化します。

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' ],
//   additionalProperties: false,
// }

代わりに reused オプションを "ref" に設定して、これらのスキーマを $defs に抽出することができます。

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

override

いくつかのカスタムオーバーライドロジックを定義するには、override を使用します。提供されるコールバックは、元の Zod スキーマとデフォルトの JSON Schema にアクセスできます。この関数は 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 をスローすることに注意してください。表現不可能なタイプのカスタム動作を定義しようとしている場合は、override と一緒に unrepresentable: "any" を設定する必要があります。

// 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" を使用します。

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 Schema が返されます。

その他のケースとして、複数の相互リンクされた JSON Schema を使用して表現したい Zod スキーマのセットがあり、おそらく .json ファイルに書き込んで Web サーバーから提供する場合などがあります。

import * as z from "zod";
 
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"});

これを実現するには、レジストリz.toJSONSchema() に渡すことができます。

重要 — すべてのスキーマは、レジストリに登録された id プロパティを持っている必要があります! id のないスキーマは無視されます。

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

デフォルトでは、$ref URI は "User" のような単純な相対パスです。これらを絶対 URI にするには、uri オプションを使用します。これは、id を完全修飾 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' ],
//       additionalProperties: false,
//     },
//     Post: {
//       id: 'Post',
//       type: 'object',
//       properties: {
//         title: { type: 'string' },
//         content: { type: 'string' },
//         author: { '$ref': 'https://example.com/User.json' }
//       },
//       required: [ 'title', 'content', 'author' ],
//       additionalProperties: false,
//     }
//   }
// }

On this page