How to use it
- Paste a JSON document, such as an API response. For a list endpoint, paste an array with several items: the more variety the sample has, the better the schema.
- Pick the draft your validator supports and the options you need. The schema updates as you type.
- Copy the schema, then review it. It describes the sample, not the API's contract, so tighten or loosen it where you know better.
- To check another response, paste it into Document to validate. Choose My schema to edit the generated schema or paste your own before validating.
How types are chosen
| JSON value | Schema |
|---|---|
"text" | {"type": "string"} |
42, -7 | {"type": "integer"} |
4.5, 1.0, 1e3 | {"type": "number"} |
true / false | {"type": "boolean"} |
null only | {"type": "null"} |
| An object | "type": "object" with properties and required |
| An array | "type": "array" with one items schema built from all of its items |
[] | {"type": "array", "items": {}}, which allows any item |
Inference rules
- Numbers are read from the text.
1is aninteger;1.0and1e3are anumber, even though JavaScript parses both to the same value as1. If one location holds both, the schema saysnumber, which accepts integers too. - Every array item is used. For an array of objects, the keys of all items are merged into one
propertieslist, in the order they first appear. requiredlists the keys present in every sample object. A key that some items leave out is optional. A key that is present butnullis still required, and its type includes"null", for example"type": ["string", "null"]. Choose Required: None to leaverequiredout.- Mixed values get a list of types. If one location holds a string in one sample and an object in another, the schema says
"type": ["object", "string"]and keeps the object'spropertiesnext to it. The object keywords only apply to objects, so strings still pass. The tool does not useanyOf. - No extra keys adds
"additionalProperties": falseto every object that has keys, so a key outside the sample is rejected. Objects that are always empty ({}) are left open, because an empty sample says nothing about which keys are allowed. - Detect string formats is off by default. When it is on,
formatis added only if every string at that location matches the same strict pattern:date-time(RFC 3339 withTand an offset, such as2026-11-04T09:30:00Z),date(a real calendar date,2024-02-29),uuid,email(a domain with at least one dot) oruri(absolutehttporhttpsURLs only). Anything else, including2026-11-04 09:30:00with a space, gets no format.uuidis not emitted for draft-07, which does not define it. - Include examples copies up to three distinct values per field into
examples. Leave it off if the sample contains real customer data you do not want in a schema file.
Validating a document on this page
The validation panel uses @cfworker/json-schema 4.1.4 (MIT). It reads the schema directly instead of compiling it to JavaScript code, so it runs under this site's strict Content Security Policy. It supports drafts 4, 7, 2019-09 and 2020-12; the draft is taken from the schema's $schema, and a schema without one is read as 2020-12 (draft-06 is read as draft-07). Every problem is listed, up to 100, with the path of the failing value (such as $[0].tags[1]), the keyword that failed and a short message. A rejected extra key is shown at the key itself; for anyOf, oneOf and not only the combined failure is shown.
formatis always checked for the formats the library knows, includingdate-time,date,time,email,uri,uuid,ipv4,ipv6andhostname. Draft 2020-12 treatsformatas an annotation by default, so a strict 2020-12 validator may accept a value this panel rejects. Unknown formats are ignored. The library's patterns are its own, so they can accept values the generator would not label (it allows a space indate-time, for example).$refmust point inside the schema. Remote schemas are never downloaded, so a$refto another URL is reported as an error.- The library documents a few unsupported parts of the official test suite, including
$dynamicRef,$vocabulary, someunevaluatedPropertiesandunevaluatedItemsedge cases, and internationalised email and host-name formats. - Before validating, the schema gets a basic structure check (for example,
"type": "strin"or apatternthat is not a valid regular expression). It is not a full check against the draft's meta-schema. - Validation runs on the page as you type. A very slow
patternin a schema you paste can freeze the tab, and extremely deep documents are reported as too deeply nested rather than validated.
Validating with the schema in Node.js
In Node.js, Ajv validates draft 2020-12 schemas with its ajv/dist/2020 build, and the ajv-formats package adds the format checks. Save the schema as schema.json and run:
import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";
import schema from "./schema.json" with { type: "json" };
const ajv = new Ajv2020({ allowUnionTypes: true });
addFormats(ajv);
const validate = ajv.compile(schema);
const data = [{ id: 1, email: "not-an-email", v: [] }];
if (!validate(data)) console.log(validate.errors);Ajv's strict mode prints a warning for a list of types such as ["integer", "string"] unless allowUnionTypes is set; a type plus "null" needs no option. For a draft-07 schema, import Ajv from ajv instead. This snippet was run on Node.js 24.21 with Ajv 8.20.0 and ajv-formats 3.0.1. To find what changed between two responses rather than whether one is valid, use JSON Diff.
Limitations
- The schema can only describe what the sample shows. A field that is never
nullor never missing in your sample becomes required and non-nullable, even if the API sometimes omits it. - No value constraints are guessed: no
enum,minimum,maxLength,patternorminItems. Add them by hand where you know the rules. - Arrays always get a single
itemsschema. Tuples (fixed positions with different types) are not detected. - Objects with the same structure in different places are written out in full each time; the tool does not create
$defsor$ref. - A key repeated inside one object keeps its last value, as
JSON.parsedoes.
Checked on 2026-11-04: schemas generated from 22 test documents (nested objects, arrays of objects with missing keys, nulls, mixed integers and decimals, empty arrays, top-level arrays and primitives, Unicode keys, 60 levels of nesting) with all 32 combinations of the options compiled in Ajv 8.20.0 strict mode, each document validated against its own schema, and documents with a wrong type, a missing required key, an extra key or a broken format were rejected.
Pasting a Flutter log or invalid JSON
A map printed by Dart's print, such as {id: 1, name: Ada}, is not JSON. Use Try to repair to convert it first, then check the guessed types. The JSON Formatter shows the exact position of other errors, and common JSON errors explains how to fix them. To get Dart classes from the same JSON instead, use JSON to Dart.