JSON Schema Generator
Paste or upload a JSON sample to draft a schema from it. Runs in your browser.
Pasted text and chosen files stay on this device. Nothing is sent to a server.
Drop a file here, choose one, or paste.
How to use it
- 1
Paste a representative sample.
- 2
Read the inferred-hint list and the required list — those are the two places the schema is claiming more than the sample shows.
What it does
A schema is a set of constraints, and the constraints a sample cannot support are the interesting ones. The two that bite are `required` — which the sample always supports and rarely justifies — and `format`, which is a guess about meaning made from a string's shape.
Walk the sample and emit a schema. Repeated shapes are hoisted into $defs and referenced. Any format keyword is emitted only with a companion note that it was inferred, and every inferred constraint is counted.
Why it works this way
`required` is the constraint a sample can never justify: every key was present because the sample is one document. It is emitted, because a schema needs one, and it is counted so the list can be reviewed rather than trusted.
`format` is a guess about meaning made from a shape. A string that looks like a date is a date only if the producer meant one, and a schema that asserts `format: date-time` will reject a payload that is perfectly valid JSON. So the hint is emitted with a note, never silently.
A shape that repeats is hoisted into `$defs` and referenced. Inlining it means two copies that can drift apart, which is the defect the reference exists to prevent.
`additionalProperties: false` is not the default here. A sample cannot show that a producer will never add a key, and forbidding extras turns a compatible change into a validation failure.
Examples
{"a": 1}{"type": "object", "properties": {"a": {"type": "integer"}}, "required": ["a"]}{"created": "2026-11-07T00:00:00Z"}{"type": "string", "format": "date-time"} ← format inferred from the shape, not from the producer{"a": {"x": 1}, "b": {"x": 2}}{"$defs": {"shape1": {"type": "object", "properties": {"x": {"type": "integer"}}}}, "properties": {"a": {"$ref": "#/$defs/shape1"}, "b": {"$ref": "#/$defs/shape1"}}}Inputs and outputs
- JSON sample
- draft: 2020-12 / draft-07
- additionalProperties: allow / forbid
- format hints: infer from shape / off
- JSON Schema
- counts: required keys, $ref hoists, inferred format hints
Edge cases
- an empty array — items cannot be inferred
- a repeated shape — $ref rather than two copies
- a string that looks like an email or a URI
- mixed-type arrays — anyOf
- integers vs numbers
- a key whose value is sometimes an object and sometimes a string
- a sample that does not validate against its own generated schema — a generator bug
Frequently asked questions
Why is everything in required?
Because every key was present in the one sample you gave. That list is a claim about your producer, not about the sample, so it is counted and meant to be reviewed.
Where did format come from?
From the shape of the string, which is a guess about meaning. Each one is listed so you can delete the ones your producer does not guarantee.
Why not additionalProperties: false?
A sample cannot show that no key will ever be added, and forbidding extras turns a compatible change into a failure.
Related tools
Sources
- JSON Schema 2020-12: Validation (required, additionalProperties, format-annotation)