Boneyard Tools

JSON to Zod Schema Generator

Paste a JSON sample and get a ready-to-use Zod schema. Nested objects become their own named schemas, arrays infer their element type, whole numbers become integers, and common string formats like email, url, uuid and datetime are detected automatically. Inferred TypeScript types come free.

How to convert JSON to a Zod schema

  1. Paste a JSON object into the input box.
  2. Optionally rename the root schema and toggle inferred types or format detection.
  3. Copy the generated schema or download it as a .ts file.

Examples

Flat object with formats

{"id":7,"email":"ada@example.com","active":true}
import { z } from "zod";

export const rootSchema = z.object({
  id: z.number().int(),
  email: z.string().email(),
  active: z.boolean(),
});
export type Root = z.infer<typeof rootSchema>;

Nested object and array

{"user":{"id":1},"tags":["a","b"]}
import { z } from "zod";

export const userSchema = z.object({
  id: z.number().int(),
});
export type User = z.infer<typeof userSchema>;

export const rootSchema = z.object({
  user: userSchema,
  tags: z.array(z.string()),
});
export type Root = z.infer<typeof rootSchema>;

Frequently asked questions

What does this tool do?

It reads a JSON sample and generates a matching Zod schema, inferring the validator for every field so you can drop runtime validation straight into your TypeScript code.

How are nested objects and arrays handled?

Each nested object becomes its own named schema, declared before the schema that references it so the const is always defined first. Arrays infer their element type as z.array(T), an array of objects gets a generated schema, and arrays with mixed values become z.array(z.union([...])).

Which string formats are detected?

When format detection is on, strings that look like an email, an http or https url, a uuid, or an ISO 8601 datetime are typed as z.string().email(), .url(), .uuid() or .datetime(). Everything else stays a plain z.string(). Turn the option off to keep all strings plain.

Are whole numbers treated as integers?

Yes. A value with no fractional part becomes z.number().int(), while a value like 3.14 stays z.number(). JSON has only one number type, so this is a best-effort guess you can adjust.

Does it generate TypeScript types too?

By default each schema is followed by an export type X = z.infer<typeof xSchema> line, so you get static types and runtime validation from one source. You can switch the type exports off.

Is my JSON sent to a server?

No. Parsing and schema generation run entirely in your browser, so your data never leaves your machine.

Why did I get an error instead of a schema?

The tool needs valid JSON with an object at the top level. Invalid syntax or a top-level array, string or number returns an error message instead of a schema.

Related tools