Generate a JSON Schema from a sample
Infer a draft 2020-12 JSON Schema from example data, with types, required arrays, nested object schemas and array item types.
- Runs in your browser
- Files are never uploaded
- Free, no account
The name given to the outermost type.
Your JSON never leaves this tab — check it yourself—
Starting the network probe…
The counter above wraps fetch, XMLHttpRequest and navigator.sendBeacon in this tab and counts every call. It does not block anything — it just reports.
Two ways to verify independently
- Turn off Wi-Fi or enable airplane mode, then use the tool. It keeps working, because the page is already fully loaded.
- Open your browser devtools, switch to the Network tab, clear it, and run the tool. No new row appears.
Why this matters
In 2025 researchers found that popular online formatters had retained tens of thousands of user-submitted snippets — JSONFormatter.org and CodeBeautify together exposed roughly 80,000 saved documents, many containing live cloud credentials, private keys and internal database connection strings, because “format this” quietly meant “upload this”. A separate incident exposed roughly 3.5 million user PDFs on a document-conversion service. The only structural fix is not sending the data in the first place: this site is served under a Content-Security-Policy whose connect-src contains no third-party origin, so a request off this device cannot be made even by accident.
What JSON Schema is for
JSON Schema is a language-independent way to describe the shape of JSON, and its value is that the same document works everywhere: Ajv in Node, python-jsonschema, Go’s santhosh-tekuri/jsonschema, OpenAPI request and response definitions, VS Code’s editor completion for config files, and form generators such as JSON Forms and RJSF. Writing one by hand for an existing payload is tedious; inferring the skeleton from a sample and refining it is much faster.
Draft 2020-12
The output declares $schema: "https://json-schema.org/draft/2020-12/schema". That is
the current release and the default in Ajv 8 and modern Python tooling. If you need an earlier
draft the differences that matter are small: draft-07 uses definitions rather than
$defs, and expresses tuple typing with an array-valued items rather than
prefixItems. Neither appears in output generated from a plain sample.
The inference rules
- Whole numbers become
"type": "integer", fractional ones"number". A field that was sometimes each becomes"number". - A key present in every merged sample of an object goes into
required; a key present in some does not. additionalProperties: falseis emitted on every object, because a schema derived from a sample should be strict by default — an unexpected key is exactly the drift you want to catch.- Arrays get an
itemsschema from the merged element type. An empty array yields an empty schema, which matches anything. - A value that was sometimes null becomes a type array, e.g.
"type": ["string", "null"]. - Mixed non-scalar types become
anyOf.
What you have to add by hand
Everything that encodes intent, because no example can reveal it:
| Keyword | Use |
|---|---|
title, description | Documentation. Editors surface these as hover text and form generators as labels. |
format | email, uri, date-time, uuid, ipv4. Note that format is annotation-only by default in 2020-12 — Ajv needs ajv-formats to enforce it. |
enum / const | Fixed value sets. The highest-value addition, and the one inference can never make. |
minimum, maximum, minLength, pattern | Range and shape constraints. |
examples, default | Documentation and tooling hints. |
$defs + $ref | Factor out a repeated shape rather than inlining it three times. |
Refactoring repeated shapes
The generator inlines nested objects rather than emitting $defs, because an inlined
schema is easier to read and easier to check against the sample. If the same shape appears in
several places, move it into $defs once and replace the copies with
{"$ref": "#/$defs/Address"}. That is a mechanical edit and it makes the
schema maintainable.
Validating with the result
Nothing on this page validates a document against a schema — that needs a full validator and
belongs in your build. The usual next step is Ajv:
const validate = ajv.compile(schema), then validate(data) and read
validate.errors. In Python, jsonschema.validate(instance, schema). Both
report the failing instance path, which is what makes a schema worth having.
Questions
Which draft does it emit?
Draft 2020-12, declared in `$schema`. It is the current release and what Ajv, python-jsonschema and most modern validators default to. Earlier drafts differ mainly in how `items` and `$defs` work; converting down is usually a small edit.
Why is additionalProperties false?
Because a schema derived from a sample should be strict by default — an unexpected key is exactly the kind of drift you want a schema to catch. Delete the line if your API is allowed to add fields without notice.
How is "required" decided?
A key that appeared in every merged sample of that object is required; a key that appeared in only some is not. As with every inference on this page, more sample records give a better answer than one.
What is not inferred?
Formats (email, uri, date-time), enums, numeric ranges, string patterns, descriptions and titles. Those encode intent, and no sample can reveal them. Add them by hand — that is where a schema earns its keep.