JSON Schema Generator
Build a draft JSON Schema from a JSON sample: field types, required keys, nested objects and arrays. Pick a draft, copy the result, download schema.json.
Why turn a JSON sample into a schema
Sooner or later, once an API or a config file starts speaking JSON, somebody asks how to describe that format in a way that can actually be checked. Writing a schema from scratch against documentation is slow. Documenting the other direction is easier when you start from a single server response: paste it in, look at what comes out, and you have a first draft. That draft shows the structure, the field names, and which keys always show up versus which ones only sometimes. From there you can do real work: validate responses, drive form fields in an editor, generate client-side types. The catch is worth stating plainly: a generator describes what it saw, not what was intended, so the result nearly always needs a human pass.
What the schema generator does
- Detects string, number, integer, boolean, null, array and object types
- Expands nested objects and arrays recursively, with no depth limit
- Marks a field required only when the key appears in every object of the sample
- Lists every field and lets you attach your own description to each
- Switches between draft-07, 2019-09 and 2020-12, and can add additionalProperties: false
How to get a schema
- Paste a JSON sample into the field: an object or an array of same-shaped objects
- Pick the specification draft and decide whether extra fields should be rejected
- Press "Build schema" and read the generated JSON
- Fill in the descriptions and rebuild if you need to adjust it
How the sample is parsed
Every value is first classified by type: a whole number differs from a fractional one, null counts as its own type, and arrays and objects are recognised by their shape rather than their contents. Next, matching keys from several objects are merged into a single property, and for each one the generator records whether the key showed up in every sample: only those end up in required. Nested objects and array elements are handled by the same routine, so the schema grows together with the data. Mixed types get special attention too: if a spot holds both a string and null, the schema gets a list of types instead of one preferred type. The whole computation is a single pass over the input JSON and runs entirely in the browser.
Examples: which type comes out and how it looks in the schema
| Value in JSON | Type in schema | Comment |
|---|---|---|
| "name": "Ivan" | string | Any string, the format is not checked |
| "id": 42 | integer | A whole number with no fractional part |
| "price": 199.5 | number | A fractional number, integer would not fit |
| "active": true | boolean | Exactly two values: true and false |
| "note": null | null | Its own type, not a string and not an empty field |
| "tags": ["a", "b"] | array with string items | The element type is inferred from the data |
| "user": { "id": 1 } | object with properties | The nested object is expanded recursively |
| "value": "7" in one record, 7 in another | [string, integer] | A mixed type, so the schema lists both |
| key present in 3 records out of 3 | required | The field shows up in every object of the array |
| key present in 2 records out of 3 | properties only | The field is optional and a validator will not demand it |
| "count": 0 | integer | Zero is a real value, not an empty one |
| empty array [] | array without items | The element type is unknown, constraints are added by hand |
Types are inferred from the values themselves, so the same key in different records can end up with different types.
Where a schema like this actually earns its keep
The first scenario is a contract between a frontend and a backend. Someone builds a form from a sample response, and a month later a validation error arrives for a field nobody ever discussed. A draft schema kept next to that sample turns a silent assumption into an explicit list of fields, and the mismatch becomes visible immediately. The second scenario is generating types for a client: the structure under properties turns into an interface or a TypeScript type, and the editor starts suggesting fields while you type.
The third scenario is checking config and data files. If a service reads YAML or JSON configuration, a schema derived from a sample is handy to keep alongside and to run every file through at startup. A typo in a key or a missing mandatory field gets caught before the service breaks in production. The fourth is documentation: the same schema works as an appendix to an API description because it shows types, nesting and requiredness in a machine-readable form. Next to a walkthrough of how a URL breaks into parts it answers most of a beginner's questions.
- A format agreement between two teams
- Form templates and hints in a code editor
- Validation of config files when a service starts
- A machine-readable description of a format in the docs
- Generating TypeScript types from a response structure
- Regression checks on a response shape after backend changes
Mistakes that produce a wrong schema
The most common mistake is treating a draft as a finished contract. A schema built from one sample looks solid: types are in place, required is filled, the structure is tidy. What it lacks is ranges, formats, enums and descriptions, and that creates an illusion of completeness. The second mistake is over-engineering types: if a field arrived as a string in the sample, should the schema forbid numbers? The strict answer depends on the server rather than the sample, and such decisions are better made explicitly than inherited from a single response.
The third mistake is not noticing mixed types. A field that arrives as a number in some records and a string in others produces a list of types in the schema, and that is not a generator failure but a warning about a real problem on the server. The fourth is forgetting nesting: if an object holds an array of objects, the required inside items follows its own logic, and it is easy to miss when editing by hand. The fifth is leaving descriptions empty, which means that someone reading the schema in six months will have no idea what a field is for. For more on formats and data structures, the piece on JSON and XML helps.
- Mistaking a draft for a complete contract
- Inheriting type strictness from a single sample
- Ignoring mixed types in the same field
- Forgetting required inside nested arrays
- Leaving descriptions blank
- Noticing fields only after the sample missed them
Walking through a sample step by step
Take a small response: an array of two objects where the first one has a note field and the second does not. The generator sees two objects, merges their keys, and counts for each key how many times it appeared. The keys id and title appeared twice out of two, so they went into required. The key note appeared once, so it lives in properties but not in required. The type of note came out as null, and that is honest: the sample held exactly null there.
Nested objects and array elements are parsed the same way: the type of a value is established first, then the keys of all encountered objects are merged, and only after that is required computed. The order matters, because required is not a property of an individual field but a conclusion about whether a key shows up in every record. That is also why a sample of a single object produces a schema where every field is mandatory: there is nothing to compare against.
What happens at each parsing step
| Step | Action | Result |
|---|---|---|
| 1 | Type detection | A value is classified as string, number, integer, boolean, null, array or object |
| 2 | Key merging | Matching keys from several objects are collected into one property |
| 3 | Counting | For every key the generator counts how many objects contain it |
| 4 | Required decision | A key found in every object ends up in required |
| 5 | Recursion | Nested objects and array elements run through the same algorithm |
| 6 | Mixed types | Different types in one field produce a list of types in the schema |
| 7 | Descriptions | The descriptions you typed are inserted into the matching nodes |
| 8 | Assembly | $schema, properties and additionalProperties are added to the nodes |
Parsing is a single pass over the input JSON and runs entirely in the browser: the sample is never sent anywhere.
What to do with the draft next
The first step after generating is to read the schema yourself and fix it by hand. Three things deserve a look: mandatory fields that do not always arrive, types the server changes from time to time, and descriptions that do not exist at all. The second step is to run the schema through the validator you will actually use in the project, against several real responses. That exposes the gap between expectation and what the server really sends and saves you from surprises in production.
The third step is to keep the schema in the repository next to the code that uses it and to update it whenever the format changes. A schema living apart from the code goes stale first. If your project is a monorepo or generates types, it helps to see how JSON to TypeScript conversion and diffing two JSON documents work: the difference shows which fields appeared and which disappeared after a server-side change.
- Read the schema yourself and fix it by hand
- Validate it with the same validator the project uses
- Run it against several real responses
- Add descriptions and constraints wherever you know them
- Keep the schema next to the code and update both together
Frequently asked questions
How is a generated schema different from a hand-written one
Why did my field not make it into required
What is the difference between integer and number in the output
Why would you turn on additionalProperties: false
Which specification draft should I pick
Can I build a schema from a single response
The schema does not describe date or email formats - why
How does this differ from online schema builders
Related tools
Regex Generator
Build a regular expression from a task template or break your own pattern down into parts
Open Graph Generator
Build og:title, og:description, og:image and Twitter Card tags for the link preview on social platforms
ASCII Table
Complete ASCII reference: codes 0–127 in DEC, HEX, OCT and BIN with search by character or code
Regex Tester & Debugger
Test regular expressions with match highlighting, groups, and common patterns
HTML Meta Tag Generator
Generate SEO-optimized HTML meta tags for your website
cURL to Code Converter
Convert cURL commands to JavaScript, Python, and PHP code
QR Code Generator
Generate QR codes from text or URLs with customizable colors and size
Cron Expression Parser
Parse cron expressions into human-readable descriptions and see next execution dates