zod-to-json-schema

Converts Zod validation schemas into standard JSON Schema, ready for OpenAPI, OpenAI, and JSON Schema draft 7 consumers.

Library
npm
v3.25.2
1,249 stars
ISC

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
45 /100 Fair
Development Activity 4
Maintenance 20
Community 56
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
82 /100 Excellent
Architecture 82
Code Quality 88
Innovation 72
Learning Curve 85

zod-to-json-schema takes a Zod schema — the runtime validator most TypeScript projects already use for parsing input — and walks its internal definition tree to emit an equivalent JSON Schema document. That output can be handed to anything that expects standard JSON Schema: OpenAPI documentation generators, form builders, LLM function-calling tool definitions, or third-party validators.

Rather than reimplementing Zod’s type system, the library recursively parses each Zod type’s internal _def and matches it against a per-type parser (string, number, object, union, effects, etc.), threading a shared Refs context through the recursion to resolve $ref pointers for recursive and repeated schemas. It supports targeting JSON Schema draft 7, the 2019-09 draft, OpenAPI 3.0, and an OpenAI strict-mode profile, with dozens of configurable strategies for dates, emails, base64 strings, and additional-properties handling.

What You Get

  • A zodToJsonSchema() function that converts any Zod schema (object, union, array, effects, branded types, and more) into a JSON Schema object
  • Per-type parsers for the full Zod type surface — strings with pattern/format handling, numbers, enums, native enums, records, maps, sets, tuples, intersections, discriminated and plain unions, recursive types via $ref
  • Multiple output targets: JSON Schema draft 7 (default), JSON Schema 2019-09, OpenAPI 3.0, and an OpenAI strict-mode profile for structured tool-call schemas
  • Fine-grained strategy options for dates, emails, base64 strings, regex patterns, $ref resolution, and additional-properties behavior
  • An override and postProcess callback API for injecting custom JSON Schema output at specific nodes without forking the library

Common Use Cases

  • Generating OpenAPI request/response schemas from the same Zod schemas already used to validate API input, avoiding schema drift between validation and docs
  • Producing JSON Schema tool/function definitions for LLM function-calling APIs (including an OpenAI strict-mode target purpose-built for this)
  • Feeding form-generation or UI-schema libraries that consume standard JSON Schema instead of Zod’s TypeScript-only API
  • Publishing a public JSON Schema contract for a data shape defined internally with Zod, so non-TypeScript consumers can validate against it

Under The Hood

Architecture: The entry point zodToJsonSchema() (src/zodToJsonSchema.ts) builds a Refs context via getRefs() (src/Refs.ts) that carries the active options, a seen map for cycle detection, and the current JSON pointer path, then calls parseDef() (src/parseDef.ts) on the schema’s internal _def. parseDef dispatches to selectParser.ts, which pattern-matches the Zod type name against one of ~30 per-type modules in src/parsers/ (object.ts, union.ts, effects.ts, record.ts, and so on), each returning a JsonSchema7Type fragment. Recursive or repeated schemas are detected through the seen map and re-emitted as $ref pointers instead of being re-expanded, and the final pass assembles definitions/$defs and the $schema header based on the chosen target.

Tech Stack: Written entirely in TypeScript (99.6% of the codebase) with zod as a peer dependency supporting both v3 schemas and a v3-compatibility mode under Zod v4. The build pipeline uses tsc for type-only, CJS, and ESM output separately (tsconfig.cjs.json / tsconfig.esm.json / tsconfig.types.json) with small tsx post-processing scripts (postcjs.ts, postesm.ts) to fix up the emitted files. ajv, ajv-formats, and a local dist-test harness are used only in dev to validate generated schemas actually parse as JSON Schema.

Code Quality: Test coverage is unusually deep for a library this size — roughly 6,400 lines of tests against 2,400 lines of source, with a dedicated test file per parser under test/parsers/ plus cross-cutting suites (allParsers.test.ts, issues.test.ts, openApiMode.test.ts, openAiMode.test.ts) that exercise every target and strategy combination. Types are strict throughout, with the Options<Target> generic threading the selected output target through the whole call chain so target-specific fields stay type-checked at the call site.

API Design: The public surface is a single function with a well-documented options object (defaultOptions in Options.ts, mirrored by a large table in the README) rather than a class or builder, so a first call needs zero configuration — zodToJsonSchema(mySchema) works out of the box, with named strategy options only needed for edge cases like recursive refs or OpenAI-specific output. The one friction point is that the project is now in maintenance-off mode, with the README pointing new users toward Zod v4’s native z.toJSONSchema() instead.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers