JSON Schema validator
Check a JSON document against a JSON Schema (draft 2020-12 subset) and get a table of every error with its location, plus a list of any keyword that was not checked.
A clear answer. Here’s how.
Checks a JSON document against a JSON Schema with a validator written by hand for a subset of draft 2020-12; nothing is generated or evaluated from your schema. Enforced keywords: type (including lists of types, and 1.0 counts as an integer), enum, const, properties, required, additionalProperties, patternProperties, propertyNames, minProperties, maxProperties, items, prefixItems, minItems, maxItems, uniqueItems, contains with minContains and maxContains, minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, minLength and maxLength (counted in code points), pattern, allOf, anyOf, oneOf, not, if, then, else, dependentRequired, dependentSchemas, unevaluatedProperties, unevaluatedItems, and $ref, $dynamicRef, $defs, $id, $anchor and $dynamicAnchor within the pasted schema. Numbers keep their written digits and are compared as exact decimals, so 19.99 is a multiple of 0.01, 1 equals 1.0, and objects are equal whatever their key order. A pattern is run by a matcher that parses the expression itself and cannot backtrack catastrophically; it reads the subset the specification recommends plus escapes, classes and \p{…}, and a pattern that uses lookahead, lookbehind or a backreference is listed as not checked. Remote references are never fetched and are listed as not checked. Formats are checked only if you ask: date, date-time, time, email, hostname, ipv4, ipv6, uuid and uri (international host names with xn-- labels are checked only as ASCII, not against IDNA rules). Every keyword the tool does not enforce is listed in the table as Not checked: content keywords, leftovers from older drafts such as dependencies and additionalItems, formats it does not know, unknown keywords (often a spelling mistake) and a $schema that names another dialect; the headline then says the document is valid against the checked keywords instead of simply valid. The validator passes every test it is given from the draft 2020-12 JSON Schema Test Suite: 1,864 tests in 430 groups (the keyword files, the reference tests with the suite’s own remote documents supplied by the test, the nine optional format files and eleven optional files on numbers, regular expressions, ids and anchors). Not run: the two files and one reference group that validate against the meta-schema, the 38 internationalised host name tests, and two optional files about draft-07 keywords and custom meta-schemas. It does not check the schema against the meta-schema, so a wrong keyword value is reported only where this tool reads it. Limits: 1,000,000 characters per input, 100 levels of nesting, 6,000,000 evaluation steps (a schema whose branches fan out into the same definitions can multiply the work, and is stopped with a message), 1,000 errors collected and 200 shown.
How this is checked
5 reference checks passed These 5 cases were run when this page was built, on 20 October 2026, and all reproduce within the stated tolerance. The same cases are part of the automated tests that run on every change to Toolmoz. Engine version 1.
See the checks and where each expected answer comes from
Case 1
- Inputs
- JSON Schema { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://example.com/product.schema.json", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "productId": { "description": "The unique identifier for a product", "type": "integer" }, "productName": { "description": "Name of the product", "type": "string" }, "price": { "description": "The price of the product", "type": "number", "exclusiveMinimum": 0 }, "tags": { "description": "Tags for the product", "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true }, "dimensions": { "type": "object", "properties": { "length": { "type": "number" }, "width": { "type": "number" }, "height": { "type": "number" } }, "required": [ "length", "width", "height" ] } }, "required": [ "productId", "productName", "price" ] } JSON document to check { "productId": 1, "productName": "A green door", "price": 12.50, "tags": [ "home", "green" ] }
- Expected, and what Toolmoz gave
- Valid expected Yes, Toolmoz YesErrors expected 0, Toolmoz 0Keywords not checked expected 0, Toolmoz 0headline expected Valid: the document matches the schema, Toolmoz Valid: the document matches the schema
- Where the expected answer comes from
- JSON Schema tutorial, Creating your first schema: the example product at the top of the page is valid against the schema built up in the page (productId 1 is an integer, productName is a string, price 12.50 is above 0, tags has two different strings)
- Allowed difference
- exact
Case 2
- Inputs
- JSON Schema { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://example.com/product.schema.json", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "productId": { "description": "The unique identifier for a product", "type": "integer" }, "productName": { "description": "Name of the product", "type": "string" }, "price": { "description": "The price of the product", "type": "number", "exclusiveMinimum": 0 }, "tags": { "description": "Tags for the product", "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true }, "dimensions": { "type": "object", "properties": { "length": { "type": "number" }, "width": { "type": "number" }, "height": { "type": "number" } }, "required": [ "length", "width", "height" ] } }, "required": [ "productId", "productName", "price" ] } JSON document to check { "productId": 1, "productName": "A green door", "price": 0, "tags": [ "home", "green", "home" ], "dimensions": { "length": 7.0, "width": 12.0, "height": 9.5 } }
- Expected, and what Toolmoz gave
- Valid expected No, Toolmoz NoErrors expected 2, Toolmoz 2headline expected Invalid: 2 errors, Toolmoz Invalid: 2 errors
- Where the expected answer comes from
- Worked by hand from the tutorial schema: price 0 fails exclusiveMinimum 0 (it must be above zero) and the tags home, green, home fail uniqueItems because the first and third are equal; every other keyword is satisfied
- Allowed difference
- exact
Case 3
- Inputs
- JSON Schema { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://example.com/product.schema.json", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "productId": { "description": "The unique identifier for a product", "type": "integer" }, "productName": { "description": "Name of the product", "type": "string" }, "price": { "description": "The price of the product", "type": "number", "exclusiveMinimum": 0 }, "tags": { "description": "Tags for the product", "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true }, "dimensions": { "type": "object", "properties": { "length": { "type": "number" }, "width": { "type": "number" }, "height": { "type": "number" } }, "required": [ "length", "width", "height" ] } }, "required": [ "productId", "productName", "price" ] } JSON document to check { "productName": "A green door", "price": 12.5 }
- Expected, and what Toolmoz gave
- Valid expected No, Toolmoz NoErrors expected 1, Toolmoz 1
- Where the expected answer comes from
- The tutorial schema requires productId, productName and price; productId is missing, so exactly one error (required)
- Allowed difference
- exact
Case 4
- Inputs
- JSON Schema { "items": { "multipleOf": 0.01 } }JSON document to check [ 19.99, 4.001 ]
- Expected, and what Toolmoz gave
- Valid expected No, Toolmoz NoErrors expected 1, Toolmoz 1
- Where the expected answer comes from
- Exact decimal arithmetic: 19.99 = 1999 × 0.01, a whole multiple; 4.001 = 400.1 × 0.01, not a whole multiple (binary floating point gets 19.99 wrong, which is why the tool does not use it)
- Allowed difference
- exact
Case 5
- Inputs
- JSON Schema { "type": "object", "properties": { "a": { "$ref": "https://example.com/other.schema.json" } } }JSON document to check { "a": 1 }
- Expected, and what Toolmoz gave
- Valid expected Yes, against the checked keywords, Toolmoz Yes, against the checked keywordsErrors expected 0, Toolmoz 0Keywords not checked expected 1, Toolmoz 1headline expected Valid against the checked keywords (1 not checked), Toolmoz Valid against the checked keywords (1 not checked)
- Where the expected answer comes from
- By definition of the tool: a reference to another document is never fetched, so it is listed as not checked and nothing else in the schema can fail the value 1 (type object is satisfied by the document)
- Allowed difference
- exact
What this shows: the engine reproduces independently worked values for these cases. It does not prove every possible input is right. To test an answer you were given, see how to check a number; to see what is and is not checked across Toolmoz, see the accuracy ledger.
See a worked example
Worked example
A fixed demonstration, separate from the values you enter above.
- JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://example.com/product.schema.json", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "productId": { "description": "The unique identifier for a product", "type": "integer" }, "productName": { "description": "Name of the product", "type": "string" }, "price": { "description": "The price of the product", "type": "number", "exclusiveMinimum": 0 }, "tags": { "description": "Tags for the product", "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true }, "dimensions": { "type": "object", "properties": { "length": { "type": "number" }, "width": { "type": "number" }, "height": { "type": "number" } }, "required": [ "length", "width", "height" ] } }, "required": [ "productId", "productName", "price" ] }- JSON document to check
{ "productId": 1, "productName": "A green door", "price": 0, "tags": [ "home", "green", "home" ], "dimensions": { "length": 7.0, "width": 12.0, "height": 9.5 } }- Check formats
- No: formats are annotations (the 2020-12 default)
Example result
| Status | Where in the document | Keyword | Problem | Where in the schema | Line |
|---|---|---|---|---|---|
| Error | /price | exclusiveMinimum | The value is 0, but it must be greater than 0. | /properties/price/exclusiveMinimum | 4 |
| Error | /tags | uniqueItems | The items at positions 0 and 2 are equal, but all items must be different. | /properties/tags/uniqueItems | 5 |
Draft 2020-12 rules, written by hand for this page (no code is generated from your schema). Numbers are compared as exact decimals, “pattern” runs in a linear-time matcher, and remote references are never fetched. Formats are not checked (in 2020-12 they are annotations unless you ask for them).