JSON Schema Generator_
Paste a JSON document and get a JSON Schema for it, in draft 2020-12 or draft-07. Paste several samples instead and it works out which fields are optional, rather than marking every one required because it only ever saw one example.
Inference is guesswork, so every guess is labelled. When a field is required only because there was one sample, when an array was always empty, when two samples disagreed about a shape — the schema says so underneath instead of looking more certain than it is.
- Input
- One JSON document, or an array of documents treated as repeated samples of the same thing.
- Output
- A JSON Schema, plus a note for each place where something had to be assumed.
- Processing
- Every sample is observed before any schema is written, so a decision from the first document can still be revised by the fifth.
- Limits
- A schema inferred from examples describes the examples. It cannot know that a field you never saw empty is allowed to be, or that the three values you saw are the only three.
- Why several samples matter
- From one document every key looks required and every array looks homogeneous. Optionality is a fact about a set of documents, not about one, and nothing can recover it from a single example.
A schema inferred from one example is mostly a guess
Everything looks required until it does not
Given {"id": 1, "nickname": "ada"}, is nickname required? Nothing in that document answers the question. Every generator has to pick, and marking everything required is the usual choice because it is the safe-looking one — it just happens to reject valid data the moment a record omits an optional field. Paste three or four records with the top-level array set to "many samples" and the answer stops being a preference: a key present in every sample is required, and a key missing from any of them is not.
An empty array teaches nothing
"tags": [] tells you the field is an array and stops there. Most tools quietly emit items: {"type": "string"} anyway, and the schema then rejects the first record with a number in it. Here the array is left open and a note says why, which is less satisfying and more accurate. The same applies to a field that was null in every sample: its type is "null", because that is genuinely all that was observed.
Arrays are merged, not sampled
An item schema taken from the first element is wrong whenever the array is mixed, and mixed arrays are common in real data. Every element is observed here and the results combined: two primitive types become a type union, an object next to a number becomes anyOf, and objects with different keys merge into one shape whose required list is the intersection. That is more work than reading element zero and it is the difference between a schema that validates your data and one that validates your first row.
The draft you name changes the syntax
Draft 2020-12 is current and is the default here. Its most consequential break from draft-07 is that tuple validation moved: items used to accept an array to describe positional elements, and now means "every element", with prefixItems taking the tuple role. A generator that writes draft-07 shapes under a 2020-12 $schema produces something that validates differently from how it reads, and nothing warns you. Switching the draft here switches the syntax as well as the URL.
Paste, choose how strict, take the schema
- 01Paste one JSON document. The schema appears immediately, with notes underneath for anything that had to be assumed.
- 02Have several records? Paste them as a JSON array and tick "Top-level array is many samples" — that is what turns required from a guess into a measurement.
- 03Tighten or loosen with the switches. "No extra properties" closes every object; "Detect enums" turns small repeated string sets into an enum, which is off by default because it is the guessiest thing here.
- 04Test it: paste another record into the box at the bottom and it will tell you which fields fail and where.
Four things people generate a schema for
Validating an API response in tests
You have a recorded response and want a contract from it.
several recorded responses
a schema with real optionality
Documenting a config file
Editors offer completion when a config has a schema.
"$schema" to the config
autocomplete and inline errors
Constraining a model’s output
Structured output needs a strict schema.
No extra properties
additionalProperties: false throughout
Finding out why a record was rejected
One record fails and the message is unhelpful.
into the test box
the exact path that failed
What is inferred, and how confident it is
| Observed | Emitted | How much of a guess |
|---|---|---|
| A whole number | "type": "integer" | Safe until a fractional value appears, then the field widens to number |
| A key in every sample | required | A measurement with several samples; a pure assumption with one |
| A key missing from any sample | Left optional | Reliable — absence is evidence |
| A null beside a string | ["string", "null"] | Reliable |
| A null in every sample | "type": "null" | Literal. It is all that was seen, and probably not what you meant |
| An empty array | "type": "array", no items | Deliberately silent — guessing the item type is how schemas reject valid data |
| A mixed array | anyOf, or a type union | Reliable, because every element was merged rather than sampled |
| A date-shaped string | "format": "date" | Advisory. JSON Schema does not require validators to enforce format |
| A few repeated strings | enum | The guessiest thing here, which is why it is off by default |
Everything in the last column appears as a note under the schema as well, against the path it applies to, so nothing has to be remembered from this table.
What changed between draft-07 and 2020-12
| Concern | draft-07 | 2020-12 |
|---|---|---|
| Tuple items | items: [A, B] | prefixItems: [A, B] |
| Every element | items: A | items: A — same spelling, and now the only meaning |
| Extra tuple elements | additionalItems | items takes that role |
| Identifier | $id with a trailing # by convention | $id without one |
| Reusable definitions | definitions | $defs |
$schema URL | http://json-schema.org/draft-07/schema# | https://json-schema.org/draft/2020-12/schema |
This generator emits neither prefixItems nor definitions, because inference from examples never produces a tuple or a shared definition. The distinction matters when you hand-edit the result.
Getting a schema you can trust
- Paste as many real records as you can, as an array, with "many samples" ticked. Nothing else improves the result as much, and it is the only way to learn which fields are optional.
- Include the awkward records deliberately — the one with the null, the one missing a field, the one with an empty list. A schema built only from tidy examples rejects the untidy ones.
- Leave enum detection off unless you genuinely know the set is closed. Three repeated values in a sample of four are not evidence of a constraint.
- Turn on "No extra properties" for structured model output and leave it off for an API contract, where a server adding a field should not break your client.
- Treat
formatas documentation. The specification makes it advisory by default, so a validator may accept a malformed email that your schema calls an email. - Run the result past the test box with a record you know is bad, not just one you know is good — a schema that accepts everything passes the happy path too.
What an inferred schema cannot know
It describes your examples, not your data model
If no sample had an empty string, nothing forbids one. If every id happened to be positive, no minimum is emitted. Inference can only narrow to what it saw, and what it saw is a sample rather than the specification. Treat the output as a first draft to edit, not a finished contract.
One sample makes everything required
That is stated in a note whenever it happens, because it is the single most misleading thing a generator does silently. A schema that marks an optional field required will reject perfectly good records, and it will do it in production rather than in the test that generated it.
format is advisory unless you opt in
JSON Schema says validators are not required to enforce format, and many do not by default. A schema that annotates a field as an email is documentation until you turn on format assertion in whichever validator you use. Do not rely on it for input validation.
The test box is not a JSON Schema validator
It understands the subset this generator emits — type, properties, required, items, enum and anyOf — and nothing else. That is enough to check a record against the schema above and is not a general validator. For a schema you have hand-edited, use a real implementation.
A top-level array is genuinely ambiguous
It might be the data — an array is a perfectly good document — or it might be a list of examples of one thing. The switch decides, and getting it wrong produces a valid schema for entirely the wrong shape. There is no way to infer which you meant.
How the inference works
- Two passes
- Every sample is observed into an intermediate structure before any schema is written, so a conclusion drawn from the first document can still be revised by the fifth. Writing as it goes would make the first record authoritative
- Required
- A key is required when it appeared in every object seen at that position. With one sample that is every key, and a note says so against the path
- Numbers
- integer until a fractional value appears anywhere in the field, at which point the whole field becomes number with a note. A field is not an integer that sometimes is not
- Arrays
- Item schemas are merged across every element of every array, never taken from the first. Disagreement between kinds produces anyOf; disagreement between primitives produces a type union
- Formats
- date-time, date, time, uuid, email, ipv4 and uri, all registered by the specification. Applied only when every observed value of the field matches the same one — inventing format names would produce schemas no validator understands
- Enums
- Off by default. When on, a string field qualifies at six or fewer distinct values across at least three samples, and the values are sorted so the same data always yields the same schema
- Draft
- 2020-12 by default with the https identifier; draft-07 available. Neither prefixItems nor definitions is emitted, because inference from examples produces no tuples and no shared definitions
- Limits
- Distinct string values are tracked to 200 per field before enum detection gives up on it, so a large document cannot grow the working set without bound
- Scope
- Inference and a subset validator. Formatting and validating JSON itself belong to the JSON formatter, and querying it to the JSONPath tester
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Questions about generating a JSON Schema
How do I create a JSON Schema from JSON?
Paste the document above and the schema appears immediately. For a schema worth trusting, paste several real records as a JSON array and tick "Top-level array is many samples" — that is what lets it tell required fields from optional ones instead of marking everything required.
Why is every field marked required?
Because you gave it one sample, and a single document contains no evidence about optionality. A note under the schema says so whenever it happens. Add more records, or turn off "Infer required" and add the required list by hand.
Which draft should I use?
2020-12 unless something in your toolchain needs otherwise — it is the current one and what most modern validators default to. The switch changes the syntax as well as the $schema URL, which matters because the meaning of items differs between the two and a mismatch validates differently from how it reads.
Why is my empty array not given an item type?
Because nothing can be known about it. Most generators emit a string item type anyway, and the schema then rejects the first record containing a number. Leaving it open is less satisfying and more accurate; a note under the schema points at the path so you can fill it in yourself.
Will the format annotations be enforced?
Only if your validator is configured to. The specification treats format as advisory by default and many implementations ignore it unless asked. Useful as documentation and for editor hints; not something to rely on for input validation.
Can I use this for structured model output?
Yes, and switch on "No extra properties" when you do — providers that constrain output to a schema generally require every object to be closed. Check the result against a real record with the test box before wiring it in.
Is my JSON uploaded anywhere?
The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.