What this converter does
Zod is the most popular TypeScript-first validation library. You describe the shape of your data once as a schema, and Zod both validates data at runtime and infers the TypeScript type. Writing schemas for big API payloads by hand takes time. This tool generates one from a real sample in an instant.
Example
{
"id": "b3c1a2e4-7f5d-4c3b-9a1e-2d4f6a8b0c1d",
"email": "grace@example.com",
"age": 36,
"signedUpAt": "2026-01-15T08:30:00Z",
"profile": {
"bio": "Compiler nerd",
"avatar": "https://example.com/g.png"
},
"roles": [
"admin",
"editor"
]
}
import { z } from 'zod';
export const ProfileSchema = z.object({
bio: z.string(),
avatar: z.url(),
});
export const UserSchema = z.object({
id: z.uuid(),
email: z.email(),
age: z.number().int(),
signedUpAt: z.iso.datetime({ offset: true }),
profile: ProfileSchema,
roles: z.array(z.string()),
});
export type Profile = z.infer<typeof ProfileSchema>;
export type User = z.infer<typeof UserSchema>;
Nested schemas are declared before the schemas that use them, so the file compiles as-is. Each schema also gets an
exported type through z.infer.
Using the generated schema
import { UserSchema, type User } from './user.schema';
const res = await fetch('/api/me');
const result = UserSchema.safeParse(await res.json());
if (!result.success) {
console.error(result.error.issues); // precise, per-field errors
} else {
const user: User = result.data; // fully typed
}
Detected types and formats
| JSON value | Zod 4 | Zod 3 |
|---|---|---|
| Integer | z.number().int() | z.number().int() |
| Decimal | z.number() | z.number() |
z.email() | z.string().email() | |
| URL | z.url() | z.string().url() |
| UUID | z.uuid() | z.string().uuid() |
| ISO date-time | z.iso.datetime({ offset: true }) | z.string().datetime({ offset: true }) |
| ISO date | z.iso.date() | z.string().date() |
| Mixed types | z.union([...]) | |
| Sometimes null | .nullable() | |
| Sometimes missing | .optional() | |
A format is only applied when every sample value matches it. Disable Detect string formats if you'd rather start with plain z.string().
Next steps after generating
- Replace string fields with a fixed set of values with
z.enum([...]). - Add constraints like
.min(),.max()or.positive()where they matter. -
Use
.strict()on objects if unknown keys should be rejected rather than stripped. - Only need types without validation? Use JSON to TypeScript instead.
Frequently asked questions
How do I generate a Zod schema from JSON?
Paste a JSON sample into the tool above. It builds a z.object() schema for every object, detects integers, nullable and optional fields, and recognizes emails, URLs, UUIDs and ISO dates. It also exports the inferred TypeScript type for each schema.
Does this support Zod 4?
Yes, and it is the default. Zod 4 uses top-level format helpers such as z.email(), z.url() and z.iso.datetime(). Switch to Zod 3 to get the z.string().email() style instead.
What is the difference between .optional() and .nullable()?
.optional() means the key may be missing (undefined). .nullable() means the key is present but its value may be null. The generator uses .optional() for keys missing from some array items and .nullable() for values that are null in some samples.
Why use Zod instead of just TypeScript types?
TypeScript types disappear at runtime, so they can’t catch a malformed API response. A Zod schema validates the data when your app receives it. z.infer gives you the matching TypeScript type for free, so you only maintain one definition.
Is my JSON uploaded anywhere?
No. The schema is generated entirely in your browser, so it is safe to paste internal API responses.