Developer

JSON to Zod Schema

Generate Zod schema code from JSON input data.

Loading interactive tool…

Embed this tool on your site

About this tool

Runtime type validation catches the bugs that TypeScript's compile-time checks cannot — when external APIs return unexpected shapes, when user-submitted JSON deviates from your assumptions, or when a third-party integration silently changes its contract. Zod has become a standard library for this in the TypeScript ecosystem, but writing Zod schemas from scratch for nested JSON is tedious and error-prone. JSON to Zod Schema automates the first draft: paste a JSON sample, set a Schema Name, click Convert and receive Zod v3 code with z.string(), z.number(), z.boolean(), z.null(), z.array(), z.object() and z.union() mapped from the detected values, plus an import line and a z.infer type alias. Nested objects and arrays are handled recursively. The schema is written on one line, every key is required, and arrays use z.union() for their element types — tidy those up by hand before committing.

Why use it

  • Eliminate Tedious Hand-Writing: Deep nested objects with 20+ keys would take minutes to transcribe into Zod notation by hand — the converter produces a complete draft schema in under a second.

  • Catch Runtime Shape Mismatches: TypeScript types are erased at runtime; Zod schemas are not. Pairing both means your app throws a clear parse error instead of a cryptic 'undefined is not a function' downstream.

  • Zod v3 API Output: Generated code uses z.object(), z.array(), z.union() and z.infer, and starts with import { z } from 'zod'.

  • Handles Nested Objects and Arrays: Recursive analysis produces nested z.object() and z.array() structures for objects and arrays of objects without manual transcription.

  • Great Starting Point for API Contracts: Use a real API response as the sample to auto-generate a schema, then add refinements like .min(), .email(), or .url() where the business rules require them.

  • Browser-Only, Zero Data Leakage: Your JSON payload — which may contain proprietary API structures or internal data models — never leaves the browser.

How to use

  1. Paste your JSON sample data into the JSON Input box — a real API response or a representative example object works best.
  2. Set the Schema Name (Root by default); it becomes <Name>Schema and the z.infer type name.
  3. Click Convert to generate the schema; use Beautify first if you want to reformat the input JSON.
  4. Review the output — each value maps to z.string(), z.number(), z.boolean(), z.null(), z.array(), z.object(), or z.union().
  5. For fields that may be absent or null in other responses, add .optional() or .nullable() by hand — the tool only sees the sample you pasted.
  6. Copy the generated code into your TypeScript file and validate live data with Schema.parse(data) or Schema.safeParse(data).

When it helps

  • When integrating a third-party REST API and you need a Zod schema to validate the response shape before using the data.
  • When writing a Next.js API route handler and you want to validate the incoming JSON body against a generated schema.
  • When bootstrapping a new TypeScript project and you want to quickly type a complex configuration object or fixture file.
  • When an API you consume has no OpenAPI spec and you need to reverse-engineer a schema from a real response sample.
  • When refactoring legacy JavaScript code to TypeScript and you need schemas for existing data structures already in production.
  • When building a form library or data transformation pipeline and you need Zod schemas to enforce shape at the boundary.

Examples

Simple user object (Schema Name: User)

Input
{
  "id": 42,
  "name": "Alice",
  "email": "alice@example.com",
  "active": true
}
Expected result
import { z } from 'zod';

export const UserSchema = z.object({ id: z.number(), name: z.string(), email: z.string(), active: z.boolean() });

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

Nested object with mixed array

Input
{"user":{"id":1,"role":"admin"},"tags":["dev",1],"note":null}
Expected result
import { z } from 'zod';

export const RootSchema = z.object({ user: z.object({ id: z.number(), role: z.string() }), tags: z.array(z.union([z.number(), z.string()])), note: z.null() });

export type Root = z.infer<typeof RootSchema>;

Top-level array of objects (Schema Name: Product)

Input
[{"id":1,"product":"Widget","price":9.99,"inStock":true},{"id":2,"product":"Gadget","price":24.99,"inStock":false}]
Expected result
import { z } from 'zod';

export const ProductSchema = z.array(z.union([z.object({ id: z.number(), product: z.string(), price: z.number(), inStock: z.boolean() })]));

export type Product = z.infer<typeof ProductSchema>;

Tips

  • After generating, add .strict() at the end of top-level z.object({...}) schemas to reject any extra keys not declared in the schema — this protects against API responses unexpectedly injecting additional fields.
  • Use z.coerce.number() instead of z.number() when your JSON might encode numbers as strings (common in form submissions and query parameters) to handle coercion automatically.
  • Add .email() or .url() refinements to string fields after generation when you know the semantic meaning — Zod will not infer these from the sample value alone.
  • Use safeParse() instead of parse() in production to get a typed result object instead of a thrown error, making error handling more predictable in async contexts.
  • For API responses with a data: { ... } wrapper envelope, generate the full response schema and use Schema.shape.data to extract the inner type without regenerating.

Frequently Asked Questions

What version of Zod does the generated code target?
The output targets Zod v3, the current major version as of 2026. The generated code uses the z.object(), z.string(), z.array(), and z.infer<typeof Schema> patterns standard in Zod v3 and compatible with all modern TypeScript toolchains.
How are null values handled in the schema?
When a JSON value is null, the tool emits z.null(). If you expect the field to sometimes be a string and sometimes null, you can manually change it to z.string().nullable() or z.union([z.string(), z.null()]) after generation.
What happens if my JSON has an array of mixed types?
The tool infers a schema for every element and wraps the distinct results, sorted, in z.union([...]) inside z.array(). For example ["dev", 1] becomes z.array(z.union([z.number(), z.string()])). An empty array becomes z.array(z.any()).
Does the tool generate z.infer types I can use in TypeScript?
Yes. The output exports <Name>Schema and a matching type alias, export type <Name> = z.infer<typeof <Name>Schema>, using the Schema Name you enter (Root by default), so runtime validation and static typing come from one source.
Can I generate schemas for arrays at the top level?
Yes. If you paste a JSON array as the root, the schema becomes z.array(...) of its elements. Note that an array with two or more elements of the same type is currently written as a one-member z.union([...]), which TypeScript rejects because z.union needs at least two options — replace z.union([X]) with X after copying.
How do I handle optional fields not present in my sample?
Any field missing from the sample but potentially present in real data cannot be auto-detected. After generation, add .optional() to any field that may be absent — e.g. change z.string() to z.string().optional(). Reviewing API documentation alongside the generated schema is recommended.
Does the tool handle deeply nested objects recursively?
Yes. Nested objects become nested z.object({ ... }) calls and nested arrays become nested z.array(...) calls. The whole schema is written on a single line, so run it through Prettier or your editor's formatter if you want one key per line.
Can I use the generated schema with tRPC or React Hook Form?
Yes. Zod schemas integrate natively with tRPC input validators and React Hook Form's zodResolver. The generated output can be passed directly to these integrations with no modification for standard field types.

Explore the category

Glossary

Zod
A TypeScript-first schema declaration and validation library. Zod schemas describe the expected shape and type of data and can parse and validate values at runtime.
z.infer
A Zod utility type that extracts a static TypeScript type from a Zod schema, so you can use the schema as both a runtime validator and a compile-time type annotation.
parse() vs safeParse()
parse() throws a ZodError on validation failure; safeParse() returns { success: true, data } or { success: false, error } without throwing, enabling non-exceptional error handling.
Schema Inference
The process of deriving a type schema from a concrete data sample by inspecting the types and structure of its values rather than manually authoring the schema.
Runtime Validation
Type checking performed while the program is executing, as opposed to compile-time checking. Essential for validating data arriving from external sources like APIs or user input.
Refinement
A custom validation rule added to a Zod type with .refine() or built-in methods like .email(), .min(), .max(), .url(). Refinements add business-logic constraints beyond basic type checking.
A LITTLE HELP. A LOT DONE.
Good tools.
Great flow.

Your shortcut to the everyday. Create, convert, calculate,
and get back to what you love.

✓ Free to use✓ No sign-up✓ 500+ possibilities