JSON to TypeScript, Zod and Pydantic models

Generate TypeScript interfaces, Zod schemas and Pydantic models from one JSON sample on this page. The output is checked with tsc --strict, Zod 3 and 4, and Pydantic 2 before it ships.

Runs locally in your browser
Sample JSON

Paste an API response, fixture, or configuration object. The sample stays in this browser.

Generated code
Generate from a JSON sample to create TypeScript types.

Inference is based on the supplied sample. Review IDs, nullable values, date strings, and business constraints before using generated types in production.

How to generate the three outputs

Paste a JSON sample, name the root type, press Generate types, and read the TypeScript, Zod and Pydantic versions of the same shape in the tabs. The sample is parsed by the browser on this page: nothing is uploaded and no request carries it.

The inferred names are checked against real compilers before shipping: the TypeScript output passes tsc --strict, the Zod schema parses its own sample under Zod 3 and Zod 4, and the Pydantic models import and validate the sample under Pydantic 2.

  1. Paste a JSON sample — an API response, a fixture or a configuration object.
  2. Set the root type name; spaces, dashes and underscores are folded into a capitalised name.
  3. Press Generate types (or Load example for a filled-in sample) and switch between the TypeScript, Zod and Pydantic tabs.
  4. Press Copy visible code for the tab you are looking at, then review the optional and nullable fields before you rely on them.

What the generator infers, and where it stops

The three outputs

A single JSON object becomes an interface (or a type alias when the sample is an array or a scalar), arrays become Array<…>, and an empty object becomes Record<string, unknown>. Zod gets the same shape as a schema plus a z.infer type, and Pydantic gets one BaseModel class per object with List, Optional, Union and Dict from typing.

The Export declarations checkbox decides whether the TypeScript and Zod lines carry export; Pydantic output is plain Python either way.

Arrays and optional fields

Every entry of an array is merged: a key that appears in only part of the objects becomes optional (role?: string in TypeScript, .optional() in Zod, Optional[…] = None in Pydantic), and a key whose values differ in type becomes a union. Objects mixed with scalars or null produce a union as well, and null never hides the other type — it is kept alongside it.

An empty array is unknown / z.unknown() / List[Any], because a sample of nothing carries no type information.

Names that have to be renamed

Keys that Python cannot spell keep their JSON spelling as an alias: {"a-b": 1} becomes a_b with alias="a-b", and class, import or None become class_, import_ or None_ so the file imports. Keys named model_config, model_dump or anything else starting with model_ are suffixed as well, because Pydantic reserves that namespace.

Two keys that would otherwise collapse into one field stay separate — {"a-b": 1, "a_b": 2} yields a_b and a_b_2 with their own aliases, and nested objects with colliding names get their own classes.

Limits and privacy

Everything runs in the tab: the conversion sends no request, and the sample is gone on reload. A 2 MB sample is typed in about 0.35 s in Chrome.

Types come from one sample, so they describe what that document contains: optional keys are the keys missing from part of an array, not the keys your API may omit, and strings stay string — no e-mail, date or UUID formats are guessed. The browser's own JSON parser reads the sample, so integers beyond 2^53 lose precision and end up as float in the Pydantic output.

Recent tools: