JSON to Zod Schema Generator

Paste sample JSON and get a ready-to-use Zod schema plus its inferred TypeScript type

import { z } from "zod";

export const userSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  name: z.string(),
  age: z.number().int(),
  active: z.boolean(),
  createdAt: z.string().datetime(),
  roles: z.array(z.string()),
  orders: z.array(z.object({
    sku: z.string(),
    qty: z.number().int(),
    note: z.null().optional(),
  })),
});

export type User = z.infer<typeof userSchema>;

Arrays of objects are merged: a key missing from some items becomes .optional(), and a key that is sometimes null becomes .nullable(). The more representative your sample, the more accurate the schema.

About this tool

The ToolNinja JSON to Zod generator turns a sample JSON payload into a Zod schema you can drop straight into a TypeScript project, plus the matching z.infer type, so runtime validation and static types come from one definition. It does more than map each value to a type. Arrays of objects are merged item by item: a key that appears in some items but not others becomes .optional(), and a key that is sometimes null becomes .nullable(). Integers become z.number().int(), and with format detection on, strings that look like emails, URLs, UUIDs, or ISO datetimes get the matching Zod refinement. The output is a starting point: a sample can only show what it contains, so tighten anything your real data guarantees (enums, min/max lengths, non-empty arrays) by hand. Everything runs in your browser.

When to use it

  • →Validating API responses at runtime instead of trusting a type assertion
  • →Bootstrapping form or request-body validation from an example payload
  • →Replacing a hand-written TypeScript interface with a schema that also validates
  • →Typing third-party webhook payloads from a captured example

Tips

  • ◆Paste an array with several varied items rather than a single object — more samples give more accurate optional/nullable detection.
  • ◆Turn off format detection if you don't want .email() or .url() refinements rejecting slightly malformed real-world data.
  • ◆Keys that aren't valid JavaScript identifiers (like "first-name") are quoted automatically.

Frequently asked questions

What's the difference between this and JSON to TypeScript?

A TypeScript interface only exists at compile time; it can't stop bad data arriving from an API at runtime. A Zod schema validates the data when it arrives, and z.infer gives you the same static type, so you get both from one definition.

Does it work with Zod 4?

Yes. The generated code uses the chained z.string().email() style, which works in Zod 3 and is still supported in Zod 4, so it runs on either version.

Why is a field marked optional when it's always present in my real data?

Because it was missing from at least one item in the sample you pasted. Remove .optional() by hand, or paste a sample where every item includes the field.

Related tools

🥷 ToolNinja