JSON Schema Generator
Automatically generate JSON Schema from your data
The JSON Schema Generator reads a sample JSON document and produces a Draft-07 schema describing its structure: types, nested objects, and arrays. It is built for API developers who want a validation starting point without hand-writing every property, and for teams that need to document a JSON payload quickly.
How to Use
Paste a sample into the input box, or press the sample button to load a demo object. Press Generate. The tool parses the JSON, walks the structure, and prints a formatted schema into the output box. Review the result, then copy it into your validator, contract tests, or documentation. Invalid JSON is reported as an error instead of producing partial output.
What the Generated Schema Contains
The output always begins with "$schema": "http://json-schema.org/draft-07/schema#". Beyond that it emits:
typefor every node: object, array, string, integer, number, boolean, or null.propertiesfor each key of every object, recursively.itemsfor arrays, inferred from the first element.
It does not emit required, enum, format, pattern, numeric bounds, or oneOf. Those keywords exist in the underlying library but the generation path used by the page produces only type, properties, and items. Treat the result as a structural skeleton and add your real constraints afterward.
Worked Example
Input:
{
"name": "John Doe",
"age": 30,
"isActive": true,
"tags": ["developer", "designer"],
"address": { "city": "San Francisco", "zipCode": "94105" }
}
Output (abbreviated):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"isActive": { "type": "boolean" },
"tags": { "type": "array", "items": { "type": "string" } },
"address": {
"type": "object",
"properties": {
"city": { "type": "string" },
"zipCode": { "type": "string" }
}
}
}
}
Because no required array is present, a validator accepts {} as valid against this schema. That is usually not what you want, so add "required": ["name", "address"] and any format rules manually.
Draft-07 and Compatibility
Draft-07 is a widely supported dialect. Ajv handles it in JavaScript, the jsonschema package handles it in Python, and most schema tooling still accepts it. Newer specifications such as 2020-12 change a few keywords, and OpenAPI 3.1 is built on 2020-12, so a Draft-07 schema may need small edits before it drops cleanly into an OpenAPI 3.1 file. The $schema line tells consumers which dialect to use, so leave it in place. Draft-07 also allows boolean schemas and conditional keywords such as if, then, and else; the generator does not emit them, but you can add them by hand.
Inference Limits You Should Know
Only the first array element is inspected. An array such as [{"a":1},{"b":2}] is described as items of an object with property a; the second shape is invisible. Empty arrays get empty items and will not constrain anything. Every string is plain string with no format, so emails, dates, and UUIDs look identical. Nulls are preserved as type: null, which permits only null in strict validators; if a field is sometimes null and sometimes a string, the schema will be wrong for one of those cases. Duplicate keys in the source are resolved by JSON.parse, so only the last occurrence survives. Finally, because inference is based on one example, a field that happens to be an integer today will be locked to integer even if the API later returns decimals. Object key order matches the sample, but property order is not significant for validation, and the input must be strict JSON, so comments and trailing commas are rejected.
Extending the Skeleton Into Real Validation
The generated schema parses, but by itself it accepts too much. The usual next step is to add required fields, formats, and bounds.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["name", "address"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"email": { "type": "string", "format": "email" },
"isActive": { "type": "boolean" }
}
}
Add required for the fields that must always be present. Add format for strings that represent emails, dates, or URIs, keeping in mind that some validators ignore format unless format assertion is explicitly enabled. Add minimum, maximum, minLength, and pattern for the rules a single sample cannot reveal.
If you have several samples, merge them by hand. The library behind the page can detect keys present in every sample, build an enum from a small set of repeated values, and combine differing shapes with oneOf, but the page feeds it one document. Those refinements are yours to apply. To actually validate, save the file as schema.json and compile it with Ajv in JavaScript, or pass it to jsonschema.validate(instance, schema) in Python.
Common Mistakes
Expecting the generator to mark required fields. Feeding it a minimal example and assuming every property the API can return will appear. Relying on it to detect enum-like values, string formats, or numeric ranges. Pasting an array of records and assuming all records were analyzed. And shipping the raw output as production validation without adding the constraints the sample cannot express. One more: pasting a JSON string that itself contains JSON and expecting the inner document to be described; only the top-level string type is inferred.
Related Tools
Frequently Asked Questions
Why is there no required array in the generated schema?
The generator infers structure from a single JSON value, so every key it sees is treated as optional. It does not emit a required list at all. Add required yourself for the fields that must always be present.
What draft version does this target, and will it work with OpenAPI 3.1?
The output declares Draft-07 via $schema. It is accepted by Ajv, Python's jsonschema, and most validation tools. OpenAPI 3.1 uses JSON Schema 2020-12 instead, so treat the generated schema as a starting point and adjust the dialect if you paste it into an OpenAPI 3.1 document.
How does the tool decide between integer and number?
It checks whether each numeric value is a whole number. A sample containing 30 and no decimal point becomes integer; a value such as 3.14 becomes number. A property that could be either is typed from whatever the single sample holds.
Does it inspect every element of an array?
No. For array values the generator inspects only the first element and uses it to describe the items. Later elements with a different shape are ignored, and a mixed-type array is not represented as oneOf.
Can it detect email, date-time, or UUID formats?
No. Every string is emitted as type string with no format keyword. Inference from values alone cannot tell an email address from an ordinary sentence, so add format, pattern, or length constraints by hand.
What happens with an empty object or an empty array?
An empty object produces a schema with type object and an empty properties map. An empty array produces type array with empty items, because there is no first element to inspect.
Reviewed by the HandyTools Hub team · Last updated