JSON to Zod Schema Converter
Generate Zod schemas and TypeScript types from sample JSON.
Runs in your browser Your input never leaves your device.
Report a problem with this tool
About this tool
Paste a sample of your JSON and get Zod schemas you can use to validate data at runtime, plus the TypeScript types derived from them with z.infer. Nested objects become their own named schemas, defined before they are used; lists become z.array; a key that is missing from some items of a list gets .optional(); null becomes z.null() or .nullable(); whole numbers become z.number().int(); values that differ in type become z.union. Empty objects become a record of unknown values and empty lists an array of unknown. The shape is inferred from your sample: objects become named types, lists become list types, a key that is missing from some items of a list becomes optional, numbers without a fraction become integers (a list that mixes 1 and 2.5 is decimal), and a value that is sometimes one type and sometimes another becomes a union or a general type. The same shape in two places shares one type. Keys that are not valid names, such as 'user name', are converted and the original key is kept. We checked the output with the real zod package: for 37 samples the generated schema parsed its own sample, and a copy of the sample with one value damaged was refused. The code works with Zod 3 and 4. Your JSON is processed in your browser and never uploaded. A JSON number such as 10.0 or 1e3 is read as a whole number, because the sample loses how it was written; tick Treat all numbers as decimals if your values can have a fraction.
How to use it
- Paste a sample of your JSON, a longer or more varied sample gives a better result.
- Set the name of the top-level type, and the options.
- Copy the code into your project.
- Adjust names and types that the sample could not tell, such as dates in strings.
Common problems
- The schema is too strict
- The sample only shows what you gave it. If a field can also be missing, null or another type, include such a case in the sample, or loosen the schema by hand.
- Dates and emails are plain strings
- The sample cannot say whether a string is a date. Replace z.string() with z.string().datetime() or z.string().email() where you know.
- A key with a space
- It is written in quotes as a property name and the schema works as usual.