JSON Schema Generator
Paste JSON samples and get a JSON Schema that accepts them, ready to refine.
The schema updates as you type. You can drop a .json or .jsonl file here — it is read on your device, never uploaded.
About the JSON Schema Generator
Paste a JSON document — an API response, a config file, a record from a log — and get a JSON Schema that describes it: the type of every field, which keys are required, which fields can be null, and formats such as date-time, email, uri and uuid where every value has them. Paste several samples (JSON Lines, or documents one after another) and the generator learns from all of them: a key that appears in only some samples becomes optional, and a field that is sometimes null becomes nullable.
Choose draft 2020-12 or draft-07, and decide whether to forbid extra keys, turn small sets of repeated values into enums, and add examples and titles. Every schema the generator writes accepts the samples it came from — that is tested with the same engine as the JSON Schema Validator, formats included. This is JSON Schema for validating data; for schema.org markup in web pages, use the Schema Markup Generator.
How to use it
- Paste a JSON sample, open or drop a file, or press Load sample. For several samples (JSON Lines, or values one after another), choose Several samples.
- Pick the draft: 2020-12 (the current version, also the one OpenAPI 3.1 uses) or draft-07 (for validators that do not support 2020-12 yet).
- Set the options: required keys, extra keys allowed or forbidden, formats, enums for small sets of repeated values (and their size limit), examples and titles, and an optional title and description for the schema.
- Copy or download the schema. Validate in the JSON Schema Validator opens that tool with your first sample as the document and copies the schema, ready to paste into its JSON Schema box.
Examples
{"id": 7, "email": "[email protected]", "score": 4.5, "tags": ["a"], "manager": null}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string", "format": "email" },
"score": { "type": "number" },
"tags": { "type": "array", "items": { "type": "string" } },
"manager": { "type": "null" }
},
"required": ["id", "email", "score", "tags", "manager"]
}Shown compactly. With a single sample every key is required and manager can only be null — add samples to teach the generator more.
{"a": 1, "b": "x"}
{"a": 2, "b": null, "c": true}
{"a": 3}"properties": {
"a": { "type": "integer" },
"b": { "type": ["string", "null"] },
"c": { "type": "boolean" }
},
"required": ["a"][{"status": "paid"}, {"status": "refunded"}, {"status": "paid"}]"status": { "type": "string", "enum": ["paid", "refunded"] }With Enums ticked: a field becomes an enum when its values repeat and there are no more than the limit (5 by default).
Common uses
- Writing a first schema for an API, a webhook payload or a message queue from real examples, then tightening it by hand.
- Documenting the shape of JSON Lines logs or exported records, including which fields are optional.
- Starting the request and response schemas of an OpenAPI description from captured traffic.
- Producing a schema to check configuration files in CI or in an editor that understands JSON Schema.
How the schema is inferred
- Types:
integerwhen every number is written without a fraction or an exponent, otherwisenumber;string,boolean,array,objectandnullas seen. A field with several kinds of value gets a list ("type": ["number", "string"]), oranyOfwhen the kinds need their own keywords (an object and a string). - required: the keys present in every object at that place. With one sample that is all of them.
- Nullable: a field that is sometimes
nullgets"null"added to its type. - Arrays: all items are merged into one
itemsschema, so[1, "a"]gives items of type number or string. - Formats:
date-time,date,time,email,uri,uuid,ipv4,ipv6andduration, only when every string at that place has the format. Times need an offset (10:30:00Z), as RFC 3339 requires, so a local time such as10:30:00stays a plain string;urineeds a scheme such ashttps://, so text likeenv:prodis not taken for one. - enum (optional): strings or integers whose values repeat, with no more different values than the limit.
Draft 2020-12 or draft-07?
For the schemas this tool writes, the two drafts differ only in $schema: the keywords used (type, properties, required, items, enum, format, additionalProperties, examples, anyOf, title, description) mean the same in both. Choose 2020-12 unless the validator or tool that will read the schema only supports draft-07. In both drafts format may be treated as an annotation unless the validator is set to check it.
Limitations
- A schema inferred from examples only knows what the examples show: check that required keys really are required, and add limits such as minimum, maxLength or pattern yourself.
- Objects used as dictionaries (keys that are IDs, such as {"user123": …}) are described key by key; rewrite them with additionalProperties or patternProperties if the keys vary.
- Arrays are described by one merged items schema; tuples (a fixed type at each position) are not detected.
Privacy
Everything happens in your browser. What you enter or open here is not uploaded or stored by MySmartCoPilot.
Frequently asked questions
Is my JSON uploaded?
No. The schema is generated in your browser, and the page works offline once loaded.
Why is every key required?
With one sample, the generator cannot tell which keys are optional, so it marks all of them as required. Choose Several samples and paste more examples, or untick Required keys to leave required out.
Why did a field get no format?
A format is added only when every value at that place has it. One value that is not a date, or a time without an offset such as 10:30:00, keeps the field a plain string. Untick Formats to never add them.
Can I use the schema with OpenAPI?
OpenAPI 3.1 schemas are a superset of JSON Schema 2020-12, so a 2020-12 schema from here works there. OpenAPI 3.0 is based on an older draft and has no "null" type: write "type": "string" with "nullable": true instead of "type": ["string", "null"], and use example instead of examples.