Skip to content

JSON to Zod Schema

Builds a Zod schema from a JSON sample, with nullable, optional and enum inference.

Turns a sample JSON document into a Zod schema — the runtime check that TypeScript types cannot give you. The output is a set of `z.object` consts in declaration order plus an inferred type for the root, so one paste gives you both the parser and the type.

🔒 Runs entirely in your browserzodjsoncodegenvalidation
Emit

Sample JSON

Drop a .json file

Read in this tab. Nothing is uploaded.

Give it every element you have. Every extra record narrows the guess — a field missing from one of them is what makes it optional.

TypeScript

How to use it

  1. Paste as many records as you have

    Every element of every array is read and merged, not just the first. Three records tell it far more than one, because a field missing from one of them is exactly what makes that field optional.

  2. Name the root type

    Nested objects are named after the key that holds them, singularised for arrays, so `users` yields a `User`. Only the root needs a name from you.

  3. Read the counts under the output

    Types, optional fields, unions and how many records were merged. A union count above zero means a field held two different kinds of value across your sample — worth looking at before you paste the result into a codebase.

  4. Paste it in and parse with it

    The blocks are emitted children-first, which matters in Zod: a `z.object` that refers to a const declared later throws at import time rather than failing to type-check. Keep the order as generated.

Common questions

Why does the schema not match my API contract?

Because it describes the sample, not the contract. A field marked optional was simply absent from one of the records you pasted; a field marked required may still be optional in an API you have not seen enough of. Treat the output as a first draft to tighten by hand.

Are there any refinements — email, uuid, min length?

None. Everything is `z.string()`, `z.number()` or `z.boolean()`, with `.int()` when every number in the sample was a whole number. Adding `.email()` because a string had an @ in it would be guessing, and a wrong refinement rejects valid data in production.

What happens to an empty array?

It becomes `z.array(z.unknown())`, because an empty array says nothing about its element type. Paste a record where the array is not empty and the schema fills itself in.

Which Zod version is this for?

The emitted calls are the ones that are the same in Zod 3 and 4 — `z.object`, `z.array`, `z.union`, `.nullable()`, `.optional()` and `z.record(z.string(), z.unknown())` in its two-argument form. Nothing version-specific is used.

Feed it from

Next

These accept what this tool produces, so the result can go straight in.