JSON Schema представляет декларативную модель описания структуры данных, тогда как Zod строится как композиционная система валидаторов в JavaScript/TypeScript. При сопоставлении этих подходов ключевым становится различие в философии: JSON Schema ориентирована на описание контракта данных, Zod — на выполнение валидации во время исполнения с возможностью преобразований и строгой типизации.
Базовые соответствия выглядят прямолинейно:
string → z.string()number → z.number()integer → z.number().int()boolean → z.boolean()null → z.null()any → z.any()Дополнительные ограничения JSON Schema транслируются через методы Zod:
minLength, maxLength →
z.string().min().max()minimum, maximum →
z.number().min().max()pattern → z.string().regex()multipleOf → пользовательская проверка через
refineJSON Schema описывает объекты через type: "object",
properties, required и
additionalProperties.
В Zod аналогичная модель выражается через
z.object({...}), где ключи объекта определяются явно.
В JSON Schema обязательные поля задаются массивом
required. В Zod обязательность определяется наличием
.optional().
// JSON Schema
{
type: "object",
properties: {
id: { type: "string" },
age: { type: "number" }
},
required: ["id"]
}
const schema = z.object({
id: z.string(),
age: z.number().optional()
});
JSON Schema использует additionalProperties, тогда как
Zod управляет этим через .strict(),
.passthrough() и .strip():
strict() — запрещает лишние поляpassthrough() — сохраняет лишние поляstrip() — удаляет неизвестные поля (поведение по
умолчанию)В JSON Schema массивы описываются через type: "array" и
items. Zod использует z.array().
// JSON Schema
{
type: "array",
items: { type: "string" }
}
const schema = z.array(z.string());
Ограничения:
minItems → .min()maxItems → .max()uniqueItems →
.refine(arr => new Set(arr).size === arr.length)JSON Schema:
enum — фиксированный набор значенийconst — строго одно значениеZod:
z.enum([...])z.literal(value)const schema = z.enum(["small", "medium", "large"]);
const constant = z.literal("fixed-value");
JSON Schema предоставляет логические операторы композиции:
oneOfanyOfallOfВ Zod аналог реализуется через:
z.union([...])z.intersection(a, b).and() и .or() в некоторых
случаяхconst schema = z.union([
z.object({ type: z.literal("a"), value: z.string() }),
z.object({ type: z.literal("b"), count: z.number() })
]);
const schema = z.intersection(
z.object({ id: z.string() }),
z.object({ timestamp: z.number() })
);
JSON Schema активно использует $ref для повторного
использования и рекурсивных структур.
Zod реализует рекурсию через z.lazy():
const Node = z.lazy(() =>
z.object({
value: z.string(),
children: z.array(Node).optional()
})
);
Прямого аналога $ref нет, но концептуально
z.lazy выполняет ту же роль отложенного разрешения
структуры.
JSON Schema поддерживает default, но не определяет
поведение выполнения. Zod интегрирует значение по умолчанию и
трансформации в саму модель:
z.string().default("value");
Трансформации:
z.string().transform(val => val.trim());
Дополнительно:
preprocess() используется для нормализации входных
данных до валидацииtransform() изменяет результат после проверкиJSON Schema допускает слабую интерпретацию типов (например, число как строка в некоторых реализациях). Zod строго следует runtime-проверкам и TypeScript-инференсу.
Особенности:
Существует экосистема инструментов, наиболее распространённый —
zod-to-json-schema.
Механизм преобразования:
Пример:
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
const schema = z.object({
id: z.string(),
count: z.number().int()
});
const jsonSchema = zodToJsonSchema(schema);
Ограничения генерации:
transform() теряютсяrefine() не всегда выражается стандартами JSON
SchemaАвтоматическое преобразование JSON Schema → Zod сложнее из-за различий в выразительности.
Основные сложности:
anyOf без дискриминатора требует сложной логики
unionpatternProperties не имеет прямого аналогаadditionalProperties может конфликтовать с
.strict()$ref требует предварительного разрешения графа
схемПри генерации Zod-схем из JSON Schema обычно:
Несовпадения моделей приводят к потере информации при конвертации:
refineformat в JSON Schema требует ручной интерпретации
(email, uri, date-time)Пример:
z.string().email();
соответствует:
{ "type": "string", "format": "email" }
но обратная интерпретация зависит от генератора.
JSON Schema:
additionalProperties: false — строгий режимtrue — разрешение любых полейZod:
.strict() — запрет.passthrough() — разрешение.strip() — удалениеРазличие проявляется в том, что Zod всегда определяет поведение на уровне рантайма, тогда как JSON Schema зависит от интерпретатора.
В типичных архитектурах Zod используется как слой runtime-валидации, а JSON Schema — как контракт для внешних систем.
Комбинированный подход:
Или обратный сценарий:
JSON Schema расширяется через format и кастомные ключи
$defs. Zod использует методы и композицию.
Сопоставление:
date-time → z.string().datetime() (или
refine)uuid → z.string().uuid()email → z.string().email()При отсутствии встроенного аналога используется:
z.string().refine(val => customCheck(val));
JSON Schema-движки часто оптимизируют проверки через заранее скомпилированные схемы. Zod выполняет цепочку валидаторов, создаваемых при объявлении схемы.
Особенность Zod:
Особенность JSON Schema:
Zod и JSON Schema пересекаются в области описания структур, но различаются на уровне исполнения: