Converts Zod schemas to JSON Schema format with support for multiple targets and extensive configuration options
The core functionality of zod-to-json-schema centers around the zodToJsonSchema function, which converts Zod schemas into JSON Schema format. This conversion supports all Zod schema types and provides flexible configuration options.
function zodToJsonSchema<Target extends Targets = "jsonSchema7">(
schema: ZodSchema<any>,
options?: Partial<Options<Target>> | string
): (Target extends "jsonSchema7" ? JsonSchema7Type : object) & {
$schema?: string;
definitions?: {
[key: string]: Target extends "jsonSchema7"
? JsonSchema7Type
: Target extends "jsonSchema2019-09"
? JsonSchema7Type
: object;
};
};Parameters:
schema: The Zod schema to convertoptions: Configuration options or a string name for the schemaReturns: JSON Schema object with optional $schema and definitions properties
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
const userSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().min(0),
isActive: z.boolean()
});
const jsonSchema = zodToJsonSchema(userSchema);// Using string name (shorthand)
const namedSchema = zodToJsonSchema(userSchema, "User");
// Using options object
const namedSchemaOptions = zodToJsonSchema(userSchema, {
name: "User",
target: "jsonSchema7"
});const addressSchema = z.object({
street: z.string(),
city: z.string(),
zipCode: z.string()
});
const personSchema = z.object({
name: z.string(),
address: addressSchema,
alternateAddresses: z.array(addressSchema).optional()
});
const jsonSchema = zodToJsonSchema(personSchema, {
name: "Person",
definitions: {
Address: addressSchema
}
});The conversion supports all Zod schema types through specialized parsers:
ZodString - Converted to JSON Schema string type with validation constraintsZodNumber - Converted to JSON Schema number type with range validationZodBigInt - Converted to JSON Schema integer type with constraintsZodBoolean - Converted to JSON Schema boolean typeZodDate - Converted based on dateStrategy optionZodNull - Converted to JSON Schema null typeZodUndefined - Converted to JSON Schema with no type (allows undefined)ZodArray - Converted to JSON Schema array type with items schemaZodTuple - Converted to JSON Schema array with fixed itemsZodRecord - Converted to JSON Schema object with additionalPropertiesZodMap - Converted based on mapStrategy optionZodSet - Converted to unique array typeZodObject - Converted to JSON Schema object with properties and required fieldsZodUnion - Converted to JSON Schema with type array or anyOfZodDiscriminatedUnion - Converted to JSON Schema anyOf with discriminatorZodIntersection - Converted to JSON Schema allOfZodLiteral - Converted to JSON Schema const or enumZodEnum - Converted to JSON Schema enumZodNativeEnum - Converted to JSON Schema enum with native enum valuesZodOptional - Removes property from required arrayZodNullable - Adds null to type arrayZodDefault - Adds default value to schemaZodReadonly - Passes through to inner typeZodBranded - Passes through to inner typeZodCatch - Passes through to inner type based on strategyZodEffects - Handled based on effectStrategy optionZodPipeline - Handled based on pipeStrategy optionZodPromise - Passes through to inner typeZodLazy - Supports recursive schema definitionsZodAny - Converted to open schemaZodUnknown - Converted to open schemaZodNever - Converted to impossible schemaZodNaN - Converted to impossible schemaThe library supports multiple target JSON Schema formats:
type Targets = "jsonSchema7" | "jsonSchema2019-09" | "openApi3" | "openAi";$schema: "http://json-schema.org/draft-07/schema#"$schema: "https://json-schema.org/draft/2019-09/schema#"The conversion process handles various edge cases:
$refZodFunction, ZodVoid, ZodSymbol return undefinedThe library includes built-in patterns for common string validations:
const zodPatterns = {
cuid: /^[cC][^\s-]{8,}$/,
cuid2: /^[0-9a-z]+$/,
ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,
email: /^(?!\.)(?!.*\.\.)([a-zA-Z0-9_'+\-\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,}$/,
emoji: () => RegExp("^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$", "u"),
uuid: /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/,
ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,
ipv4Cidr: /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/,
ipv6: /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/,
ipv6Cidr: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,
base64: /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,
base64url: /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/,
nanoid: /^[a-zA-Z0-9_-]{21}$/,
jwt: /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/
};These patterns are automatically applied when Zod string schemas use built-in validation methods like .email(), .uuid(), etc.
Install with Tessl CLI
npx tessl i tessl/npm-zod-to-json-schema