JSON to Zod Schema

Generate a Zod validation schema from a JSON sample.

Free JSON to Zod schema generator that infers a typed Zod validation schema from a JSON sample, including nested objects and arrays, with an inferred TypeScript type. Runs entirely in your browser — nothing is uploaded. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What Zod types are generated?

Primitives map to z.string(), z.number(), z.boolean() and z.null(); objects become z.object({ ... }); arrays become z.array(T), and a mixed array becomes z.array(z.union([...])). An empty array becomes z.array(z.unknown()).

Generate a Zod schema from JSON

Zod gives you runtime validation and a static TypeScript type from one schema definition, but writing the schema to match a JSON payload by hand is slow and error-prone — especially for deeply nested API responses. This tool infers a ready-to-use Zod schema plus its inferred TypeScript type from a representative JSON sample, so you can jump straight from a raw API payload to working validation in seconds.

How it works

The generator does a recursive walk of your JSON sample and maps every value to its corresponding Zod validator:

JSON valueGenerated Zod type
"hello"z.string()
42z.number()
true / falsez.boolean()
nullz.null()
{ key: value }z.object({ key: <T> })
["a", "b"]z.array(z.string())
[1, "x"] (mixed)z.array(z.union([z.number(), z.string()]))
[] (empty)z.array(z.unknown())

Nested objects are handled recursively, so even a deeply structured payload like { user: { address: { city: "London" } } } produces properly nested z.object() calls. The output also exports a matching TypeScript type via z.infer<typeof schema>, which means you get both runtime validation and a static type from a single definition — exactly what makes Zod worth using.

Worked example

Take this API response representing a blog post:

{
  "id": 7,
  "title": "Hello world",
  "published": true,
  "author": { "name": "Sam", "id": 42 },
  "tags": ["typescript", "zod"]
}

The generator produces:

import { z } from "zod";

const schema = z.object({
  id: z.number(),
  title: z.string(),
  published: z.boolean(),
  author: z.object({
    name: z.string(),
    id: z.number(),
  }),
  tags: z.array(z.string()),
});

type Schema = z.infer<typeof schema>;

You can then pass any unknown API response through schema.parse(data) and get a fully typed object — or use schema.safeParse(data) to get a result object without throwing on invalid input.

Practical guidance

What to paste as your sample. Use a real, representative response from your API, not a minimal stub. The more fields you include in the sample, the more complete your generated schema. If your payload sometimes omits a field, the schema will assume it is always present — add .optional() to those fields after generating.

Handling nullable vs optional fields. If a field can be null at runtime, the inferred z.string() will reject it. Either chain .nullable() on the field (for string | null) or .nullish() (for string | null | undefined).

Arrays with a single sample element. The array type is inferred from all the elements in your sample array. An array with one number element generates z.array(z.number()) — if the real array can also contain strings, add them to the sample before generating.

When to use this over writing schemas by hand. Manual schemas give you more control over refinements (.min(), .email(), .regex()) and discriminated unions — but they take time. Use the generator to get the structural scaffolding in place, then add refinements on top.

All inference runs entirely in your browser — your JSON is never uploaded or stored.