DevToolsmith

JSON to Zod Schema Converter

Generate a ready-to-use Zod schema from any JSON sample. Supports Zod 4 and Zod 3, detects optional and nullable fields, and recognizes emails, URLs, UUIDs and ISO dates.

Runs 100% in your browser — nothing is uploaded

JSON
Tip: drop a file here361 chars · 361 bytes · 14 lines
Zod schema
713 chars · 713 bytes · 30 lines

Tip: paste an array of several objects — keys missing from some of them become optional (.optional()).

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

JSON input
{
  "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"
  ]
}
Generated Zod 4 schema (root name: User)
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 valueZod 4Zod 3
Integerz.number().int()z.number().int()
Decimalz.number()z.number()
Emailz.email()z.string().email()
URLz.url()z.string().url()
UUIDz.uuid()z.string().uuid()
ISO date-timez.iso.datetime({ offset: true })z.string().datetime({ offset: true })
ISO datez.iso.date()z.string().date()
Mixed typesz.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.