JSONスキーマからZodスキーマへの変換器 — Numio
json-schema-to-zod を使って JSON Schema から Zod の検証コードを生成します。minLength、minimum、pattern、default などの制約はチェーンした Zod メソッドになり、"required" にないプロパティには .optional() が付きます。
他チームから JSON Schema を受け取り、JSON Schema バリデーターを使わずに TypeScript のサービスで実行時検証をしたい場合。
こんなときに使えます
- 他チームから JSON Schema を受け取り、JSON Schema バリデーターを使わずに TypeScript のサービスで実行時検証をしたい場合。
- フォームの検証を Ajv などの JSON Schema バリデーターから Zod へ移行中で、出発点となる生成コードがほしい場合。
使い方
- JSON Schema パネルに JSON Schema を貼り付けます。
- 必要に応じて設定を開き、Root Schema Name(既定は "schema")を変更します。これがエクスポートされる const の名前になります。
- "zod" から z をインポートする生成コードをプロジェクトにコピーします。変換はブラウザ内で行われます。
JSON Schema
{
"type": "object",
"properties": {
"username": { "type": "string", "minLength": 3, "maxLength": 20 },
"age": { "type": "integer", "minimum": 18 },
"contact": {
"oneOf": [
{ "type": "string", "format": "email" },
{ "type": "string", "pattern": "^\\+[0-9]+$" }
]
},
"newsletter": { "type": "boolean", "default": false }
},
"required": ["username", "contact"]
}Zod スキーマ
import { z } from "zod"
export const schema = z.object({
username: z.string().min(3).max(20),
age: z.number().int().gte(18).optional(),
contact: z.any().superRefine((x, ctx) => {
const schemas = [
z.string().email(),
z.string().regex(new RegExp("^\\+[0-9]+$")),
]
const errors = schemas.reduce(
(errors: z.ZodError[], schema) =>
((result) => ("error" in result ? [...errors, result.error] : errors))(
schema.safeParse(x),
),
[],
)
if (schemas.length - errors.length !== 1) {
ctx.addIssue({
path: ctx.path,
code: "invalid_union",
unionErrors: errors,
message: "Invalid input: Should pass single schema",
})
…仕様と制限
oneOf は、例のとおり z.any().superRefine(...) に変換され、サブスキーマのうちちょうど 1 つが通ることを検査します。
$ref は解決されません。参照しているプロパティは z.any() になります。
integer には .int()、format "email" には .email()、format "date-time" には .datetime() が付きます。
additionalProperties: false は .strict() ではなく .catchall(z.never()) になります。
FAQ
null 許容の型はどう扱われますか?
"type": ["string", "null"] は z.union([z.string(), z.null()]) になり、必須でないプロパティには .optional() が付きます。
エクスポートされるスキーマの名前を変えられますか?
はい。設定で Root Schema Name を指定すると、出力は export const schema ではなく export const <name> = ... になります。
definitions と $ref には対応していますか?
いいえ。$ref を使うプロパティは z.any() になるため、変換前に参照先のスキーマをインライン展開してください。