JSON to Zod Schema Generator

Paste a JSON sample and get a Zod schema that validates it, with the inferred TypeScript type.

Loading tool…

About the JSON to Zod

Zod validates data at run time and gives you the TypeScript type of the result. This tool writes the schema from a sample: objects become z.object({ … }), arrays z.array(…), whole numbers z.number().int(), other numbers z.number(), and null becomes z.null(). A value that is sometimes null gets .nullable(). Keys that are not valid identifiers are quoted, an empty array is z.array(z.unknown()) and an empty object z.record(z.string(), z.unknown()).

The items of an array are merged into one schema. A key that is missing from some items gets .optional(), and values of different kinds become z.union([z.string(), z.number()]). With Detect formats, strings that all have the same format get a check: .email(), .url(), .uuid(), .datetime() (with { offset: true } when a value has an offset like +02:00), .date() and IPv4. The detection is strict, so a format is only added when every sample passes the check of Zod itself.

The Zod 3 output also runs on Zod 4, except the IPv4 check. The Zod 4 output uses the newer top-level forms: z.email(), z.url(), z.uuid(), z.iso.datetime(), z.int() and z.strictObject(). Strict objects reject unknown keys instead of removing them. Export inferred type adds export type Root = z.infer<typeof rootSchema>, and nested objects can be declared as separate schemas, in the order that JavaScript needs. A schema from one sample is a draft: review the optional fields and formats.

How to use it

  1. Paste a JSON sample or open a .json file.
  2. Set the root name and choose Zod 3 or Zod 4.
  3. Toggle format detection, strict objects and separate nested schemas.
  4. Copy the schema or download schema.ts.

Frequently asked questions

What is the difference between optional and nullable?
.optional() accepts a missing key (undefined). .nullable() accepts the value null. A key that is missing in some samples and null in others gets both.
How do I use the generated schema?
Install zod, save the code in a file and call rootSchema.parse(data), which throws on invalid data, or rootSchema.safeParse(data), which returns { success, data } or { success, error }.
Why z.number().int() and not z.number()?
Every sample of that field was a whole number, so the schema rejects fractions. If the field can hold a fraction, change it to z.number(), or put a value like 1.5 in the sample.
Do I still need TypeScript interfaces?
No. z.infer<typeof rootSchema> gives the type of the validated data, so the schema is the single source for both the run-time check and the static type.

Related tools