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 browserPaste an API response, fixture, or configuration object. The sample stays in this browser.
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.
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.
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.
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.
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.
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.