curly{bits}

curlybits / JSON to Zod

JSON to Zod Schema Converter

Paste an API response or any JSON and get a ready-to-use Zod schema as you type. Nested objects become their own schemas, declared in the right order, array items are merged so every field is covered, and you get z.infer types for free. Choose Zod 4 or Zod 3 syntax.

Input JSON
Zod schema

      

How to use the JSON to Zod Schema Converter

  1. Paste JSON into the left box, or click Load sample.
  2. Pick Zod v4 or v3, and set the Root name.
  3. Keep detect email, URL, UUID, dates on to get z.email(), z.iso.datetime() and friends instead of plain strings.
  4. Click Copy and paste the schema into your project. Use RootSchema.parse(data) to validate.

Why use Zod instead of plain TypeScript types?

TypeScript types disappear when your code is compiled, so they can't check what an API, a form or a config file actually sends you at runtime. A Zod schema does both: schema.parse(data) throws a clear error when the data doesn't match, and z.infer<typeof schema> gives you the TypeScript type from the same source, so the two can never drift apart. If you only need types, use JSON to TypeScript.

How the schema is inferred

  • Numbers: whole numbers become z.int() (v4) or z.number().int() (v3); anything with decimals becomes z.number().
  • Strings with a format: if every sample value is an email, URL, UUID, ISO date or ISO date-time, you get the matching validator. Turn the option off for plain z.string().
  • null: a key that's sometimes null gets .nullable(). A key that's missing from some array items gets .optional().
  • Arrays: every item is checked, so mixed arrays become z.union([...]), and objects inside arrays are merged into one schema.
  • Order: nested schemas are declared before the schemas that use them, so the file runs as is. Objects with exactly the same shape share one schema.

Zod 4 or Zod 3?

Zod 4 (released in 2025) moved string formats to the top level, such as z.email() and z.uuid(), and added z.int() and z.strictObject(). The old z.string().email() style still works in Zod 4 but is deprecated. Pick v3 if your project hasn't upgraded yet.

Example

import { z } from "zod";

export const customerSchema = z.object({
  id: z.int(),
  email: z.email(),
  phone: z.string().nullable(),
});

export type Customer = z.infer<typeof customerSchema>;

Frequently asked questions

Is the schema exactly right for my API?

It's only as good as your sample. A field that's always present in the sample might be optional in real data, and one that's always a string might sometimes be null. Paste an array of several varied responses for a more accurate schema, then review it.

Why is a field z.null()?

Every value it had in your sample was null, so the real type couldn't be seen. Replace it with the expected type, for example z.string().nullable().

What does strict objects do?

It rejects keys that aren't in the schema instead of quietly removing them: z.strictObject() in v4, .strict() in v3.

Does it work for JSON Schema too?

No, this tool writes Zod code. Zod 4 can turn a schema into JSON Schema with z.toJSONSchema().

Is my JSON uploaded?

No. The schema is generated in your browser.

Updated

Add this JSON to Zod converter to your website

Free for blogs, schools and businesses. Copy the code below and paste it into your page's HTML. The tool works exactly like this one and runs in your visitors' browsers, so nothing is uploaded. Please keep the credit line so others can find it too.

Preview embed ↗