JSON to JSON Schema
Paste a JSON document and get a draft 2020-12 schema that describes it — each key typed from the value it holds, arrays from their items, nothing invented. It runs in your browser; the document never leaves the tab.
What you get
- Describes the API-response sample as draft 2020-12 · 34 properties · 7 objects
- Nests the schema the way the document nests: each object with its properties and its required list, each array with its items
- Writes format: date-time on a string only when every value seen is an RFC 3339 date-time, and integer only when every number seen was written whole — 149 is one, 149.00 is not
- Leaves a key out of required when some elements lack it: the paginated list's charges drop failure_message from required, because two of three charges lack it
- Types a field that is only ever null as ["string", "null"] — the one guess it makes, said here and in the reference
What it will not do
- Invent titles, descriptions, enums, minimums or patterns. It types what is there.
- Write $defs or $ref. The schema is nested like the document; a shape used twice appears twice.
- Validate anything against the schema — paste it into the validator you already use.
- Send your text anywhere. The page is static and the engine runs in this tab — open the network panel and watch it stay empty.
What you get
- An object → type, properties, required
{"id": 1, "status": "paid"}{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "integer" }, "status": { "type": "string" } }, "required": ["id", "status"] }- A key missing in some items → not required
[{"id":1,"note":"x"},{"id":2}]{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "note": { "type": "string" } }, "required": ["id"] } }- An RFC 3339 string → format: date-time
{"created_at": "2026-04-21T14:32:08Z"}{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "created_at": { "type": "string", "format": "date-time" } }, "required": ["created_at"] }- A number written whole → integer; written with a point → number
{"qty": 2, "price": 12.50, "total": 149.00}{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "qty": { "type": "integer" }, "price": { "type": "number" }, "total": { "type": "number" } }, "required": ["qty", "price", "total"] }149.00 parses to 149, so the value alone would say integer; the schema reads the number as you wrote it.
- null → a nullable string, the one guess
{"line2": null}{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "line2": { "type": ["string", "null"] } }, "required": ["line2"] }A null alone says nothing about the value; a schema that accepts only null is useless.
The sample
What the first sample opens — a real file, not an illustration written for this page.
in VS Code
Convert, then JSON Schema — from a document or a selection, into a new editor.
Questions
Which draft is it?
Draft 2020-12, named in $schema. Every keyword it writes — type, properties, required, items, format — reads the same in draft-07, so an older validator takes it too.
Why is a field required when my API sometimes omits it?
The schema describes the sample: a key present on every element is required. Paste a response that omits the field, or a list where some elements lack it, and it leaves required.
What happens when a field is only ever null?
It is typed ["string", "null"]. A lone null says nothing about the value, so this is the one place the schema guesses — and it guesses string.