zod ajv

Zod + AJV: Convert Zod to JSON Schema and Validate with Ajv

Use Zod with AJV by converting supported Zod schemas to JSON Schema, choosing the right Ajv draft, compiling validators, and avoiding unsupported Zod features.

Quick answer: should you use Zod with AJV?

Use Zod with AJV when Zod is the TypeScript source of truth but another boundary needs portable, compiled JSON Schema validation. The practical zod ajv workflow is: keep the Zod schema in app code, convert supported shapes to JSON Schema, review the output in the Zod to JSON Schema Converter when needed, then compile that JSON Schema with Ajv where untrusted JSON enters the system.

Zod vs AJV: where each belongs

Zod and AJV solve adjacent problems rather than replacing each other. Zod is best where TypeScript developers write and infer validation types; AJV is best where JSON Schema is the contract that must be compiled, shared, or enforced outside one TypeScript module.

  • Use Zod for application schemas, form validation, server actions, and API response parsing.
  • Use AJV for compiled JSON Schema validators, gateways, queues, workers, and cross-language contracts.
  • Use JSON Schema as the bridge when a Zod-owned contract needs to leave the TypeScript codebase.

Convert Zod to JSON Schema with z.toJSONSchema

For Zod 4, start with `z.toJSONSchema()` or an interactive converter that uses the same native conversion behavior for supported schemas. Pick the JSON Schema target that your Ajv instance expects before copying the schema into a production validator.

import * as z from "zod";

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  role: z.enum(["admin", "member"]),
});

const userJsonSchema = z.toJSONSchema(UserSchema, {
  target: "draft-07",
});

Use FrameworkKit before compiling with AJV

Use the browser converter when you want to compare Draft 2020-12, Draft 7, and OpenAPI output before wiring AJV into a repository script. The tool keeps the target choice and diagnostics visible for review.

Ajv Draft 7 vs Draft 2020-12 setup

Use Draft 7 when your platform or existing Ajv setup expects the default Ajv export. Use Draft 2020-12 for modern JSON Schema features, but configure the matching Ajv export so schema keywords are interpreted consistently.

import Ajv from "ajv";
import Ajv2020 from "ajv/dist/2020";

const draft7Ajv = new Ajv({ allErrors: true });
const draft2020Ajv = new Ajv2020({ allErrors: true });

Full working TypeScript example

After conversion, compile the JSON Schema once and reuse the validator at the boundary. Treat the incoming value as `unknown` until Ajv accepts it, then narrow or map the value for the rest of the application.

const ajv = new Ajv({ allErrors: true });
type UserPayload = z.infer<typeof UserSchema>;

const validateUser = ajv.compile<UserPayload>(userJsonSchema);

export function parseUserPayload(payload: unknown): UserPayload {
  if (!validateUser(payload)) {
    throw new Error(ajv.errorsText(validateUser.errors));
  }

  return payload;
}

Unsupported Zod features to review

Not every Zod behavior can become plain JSON Schema. Review unsupported or lossy conversion areas before treating the Ajv validator as equivalent to the original Zod parser.

  • Transforms and `.pipe()` can change runtime output in ways JSON Schema cannot express.
  • Custom `.refine()` and `.superRefine()` logic must be modeled manually or kept in a separate validation step.
  • `z.date()`, `z.bigint()`, `z.undefined()`, `z.map()`, and `z.set()` need deliberate JSON-friendly replacements.
  • Coercion should be designed explicitly because Ajv and Zod can handle input normalization differently.

Common Ajv errors and fixes

Most Zod to AJV issues come from draft mismatch, format validation, or assuming JSON Schema can run Zod-only code. Fix the schema contract first, then tune Ajv options.

  • If Ajv rejects a keyword, confirm the generated schema target matches the Ajv draft import.
  • If `format` checks do not run, add the format support your Ajv setup requires.
  • If nullable fields fail, verify whether the schema uses `type: ["string", "null"]`, `oneOf`, or OpenAPI-style `nullable`.
  • If extra keys behave differently, review `additionalProperties` and whether your Zod object should be strict, loose, or input-oriented.

Production checklist

Before shipping a Zod to JSON Schema to Ajv pipeline, test both the original Zod schema and the compiled Ajv validator with the same payload set. The goal is not just a successful conversion, but a contract your team can explain and maintain.

  • Pin the Zod and Ajv versions used by the conversion and validator runtime.
  • Choose Draft 7 or Draft 2020-12 deliberately and keep that choice visible in tests.
  • Add valid, invalid, nullable, optional, extra-property, and malformed payload fixtures.
  • Keep Zod-specific business rules in Zod or model them explicitly as JSON Schema constraints.
  • Document which system owns the source of truth so Zod, JSON Schema, and Ajv do not drift.

Zod, AJV, and JSON Schema roles

LayerBest use caseTradeoff
ZodTypeScript-first runtime validation, form parsing, API response parsing, and inferred app types.Zod schemas are code, so transforms and custom refinements do not always map to portable JSON Schema.
JSON SchemaPortable validation contracts for APIs, queues, gateways, schema registries, and non-TypeScript consumers.JSON Schema does not infer TypeScript types by itself and cannot run application-specific TypeScript logic.
AjvFast runtime validation of JSON Schema at service boundaries, ingestion points, and infrastructure edges.Ajv validates schema documents, so Zod-first teams need a reviewed conversion step before compiling.

Use FrameworkKit to generate the starter code, then review the output before shipping it in production.

Zod to JSON Schema Converter

Zod to JSON Schema resources

FAQ

Can AJV validate a Zod schema directly?

No. Ajv validates JSON Schema, not Zod schema objects. Convert supported Zod schemas to JSON Schema first, then compile the generated schema with Ajv.

Is Zod or AJV better for TypeScript apps?

Use Zod when validation lives inside TypeScript application code and you want inferred types. Use AJV when the contract is JSON Schema and needs compiled validation, cross-language sharing, or infrastructure integration.

Which JSON Schema draft should I use with Ajv?

Use Draft 7 for broad compatibility with the default Ajv export. Use Draft 2020-12 when you need modern JSON Schema behavior and configure the matching Ajv 2020 export.

Do Zod transforms work after converting to JSON Schema?

No. JSON Schema validators cannot run TypeScript transforms or custom refinement logic. Keep those rules in Zod or model the closest JSON Schema constraint manually.

Related comparisons

Related tools