Paste JSON and get TypeScript types plus a matching Zod schema. List items are merged. Nothing is uploaded.
To turn JSON into TypeScript, each value gets the type it has in the sample: text is string, numbers are number, true and false are boolean, and null is null. An object becomes an interface, with one property per key. A list becomes T[], where T is the type of its items. Because a sample is only a sample, the result describes the data you pasted, not every shape an API could send. Paste a list with several items, or an object with every field filled in, so the page can see all the variants. The root type is named Root unless you change it, and every nested object gets its own interface, named after its key in PascalCase: user_name becomes UserName.
The items of a list are merged into one shape. If a key is missing from some items, it becomes optional: [{"a":1,"b":2},{"a":3}] gives a: number and b?: number. If a key holds different types across items, you get a union such as string | number. A null value adds | null, and a key that is only ever null is typed null. An empty list has no items to learn from, so it becomes unknown[]. A list that holds both numbers and text becomes (string | number)[]. Types are listed in a fixed order: string, number, boolean, objects, lists, then null. Missing keys can be written as key?: T or as key: T | undefined, whichever your compiler settings need.
A list under users gets items named User, one under categories gets Category, and a list under data gets DataItem: a trailing s is dropped unless the word ends in ss, us or is, and any other word gets Item added. If two different shapes would get the same name, the second one gets a number, as in Item and Item2. Two objects with the same name and exactly the same shape share one interface. Keys that are not valid identifiers, such as first name, a-b or 1, are quoted. You can switch between interface and type, add export and add readonly. Readonly marks properties and lists, and is not applied to the Zod schema.
The second output is the same model written for Zod: z.object for objects, z.array for lists, z.union for mixed types, .nullable() for null and .optional() for missing keys. Each nested object is its own constant, written before the one that uses it, and the last line exports Root as the type that Zod infers from RootSchema. The schema checks shape and basic type only. It does not know that a number is an integer, a string is an email or a date, because JSON samples do not say so. Both outputs use the same names and the same optional keys, so the TypeScript and the schema agree.
The page reads up to 500,000 characters of strict JSON: no comments, no trailing commas, double quotes only. Errors give the line and column. It cannot tell a map with free-form keys, such as ids pointing to objects, from an object with fixed keys, so that case produces one property per key. Non-ASCII letters in a key are not used when building a type name. The code is generated in your browser and nothing is uploaded.
Paste the JSON, keep the root name as Root or type your own, and copy the TypeScript output. For {"id": 1, "name": "Ada"} you get export interface Root with id: number and name: string.
It was missing from some items in a list. With [{"a":1,"b":2},{"a":3}] the key b is in one of two items, so it becomes b?: number. A key that is present everywhere stays required, even if some values are null.
There are no items to look at, so nothing says what the list will hold. unknown[] is the safe choice: you must check each item before using it. Put one example item in the list to get a real type.
Yes. Switch Declare objects as to type and each object becomes export type Name = { ... }. Lists, unions and a root that is not an object are always written as type aliases.
Yes, both come from the same inferred model, so names and optional keys are identical. The last line, which uses z.infer, gives back the same type. Zod checks shape and basic types, not formats such as email or integer.
No. The text is processed in your browser and not uploaded. The JSON itself is never saved; only your option choices are kept on this device.