How JSON Schema validation works
A JSON Schema is itself a JSON document that describes the shape of other JSON documents. It says things like "this must be an object", "the name field is required", "the age field must be a non-negative integer", or "the email field must match a regular expression". A validator reads the schema and walks through your data, reporting every place where the data does not match the rules.
Validators are most commonly used at three places in real systems:
- API request validation — reject malformed requests before they reach your business logic, returning clear errors to the client.
- Configuration file validation — catch typos and missing fields at startup instead of at the moment the value is read.
- Test fixtures — assert that mock responses still match the contract your code expects.
This tool uses Ajv 8, the most widely used JSON Schema validator in the JavaScript ecosystem. It supports drafts 06, 07, 2019-09, and 2020-12. All validation runs in your browser — your JSON and schema never leave your device.
Common JSON Schema keywords — quick reference
These are the keywords you will use 90% of the time. Click a sample above to see most of them in action.
| Keyword | Applies to | What it does |
|---|---|---|
type | any | Restricts the JSON type. Allowed values: "string", "number", "integer", "boolean", "object", "array", "null". Can be an array for unions. |
required | object | Array of property names that must be present. Presence only — does not check for non-empty values. |
properties | object | Object mapping property names to their sub-schemas. |
additionalProperties | object | false rejects any property not in properties. A schema value validates extras. |
items | array | Sub-schema each array element must match. |
minItems / maxItems | array | Minimum / maximum number of elements. |
minLength / maxLength | string | Minimum / maximum character count. |
pattern | string | A regular expression the string must match. |
format | string | Named format like email, uri, date, date-time, uuid. |
minimum / maximum | number | Inclusive numeric bounds. Use exclusiveMinimum / exclusiveMaximum for strict bounds. |
enum | any | Array of allowed values. The instance must equal one of them exactly. |
const | any | Like enum but only one allowed value. Common in discriminator patterns. |
oneOf | any | Array of sub-schemas. The instance must match exactly one. |
anyOf | any | Array of sub-schemas. The instance must match at least one. |
allOf | any | Array of sub-schemas. The instance must match all of them. |
How to read validation errors
When validation fails, the result table shows three columns for each error:
- Path — a JSON Pointer to the exact location in your data.
/users/0/agemeans theagefield inside the first item of theusersarray. An empty path (/) means the root. - Message — a human-readable description of what went wrong, plus a small detail in parentheses (the missing property name, the expected type, the allowed enum values, etc.).
- Keyword — which JSON Schema keyword produced the error. Useful when you have several rules on the same field and want to know exactly which one failed.
For example, validating {"name": 42} against {"properties": {"name": {"type": "string"}}} produces:
Path: /name Message: must be string (expected string) Keyword: type
The path tells you exactly which field, the message tells you what was wrong, and the keyword tells you which rule fired. Read errors in that order and the fix is usually obvious.
Common validation patterns
Make a field required but allow null
JSON Schema treats null as a distinct type. To accept either a string or null:
{
"type": "object",
"required": ["nickname"],
"properties": {
"nickname": { "type": ["string", "null"] }
}
}
Validate an email
Use the format keyword. This tool supports the most common formats (email, uri, date, date-time, uuid) inline:
{
"type": "string",
"format": "email"
}
Restrict a string to a small set of values
Use enum when there is a fixed list. Use pattern when there is a rule:
{
"type": "string",
"enum": ["small", "medium", "large"]
}
Forbid unexpected keys
By default, JSON Schema accepts any extra properties not listed in properties. Add "additionalProperties": false to reject them — useful for config files where typos should fail loudly:
{
"type": "object",
"additionalProperties": false,
"properties": {
"host": { "type": "string" },
"port": { "type": "integer" }
}
}
Polymorphic data with oneOf
When a value can be one of several shapes, use oneOf with a discriminator field (often called kind or type) backed by const:
{
"oneOf": [
{ "type": "object", "required": ["kind", "last4"],
"properties": { "kind": { "const": "card" }, "last4": { "type": "string" } } },
{ "type": "object", "required": ["kind", "iban"],
"properties": { "kind": { "const": "bank" }, "iban": { "type": "string" } } }
]
}
Reuse a sub-schema with $ref
Define repeated sub-schemas once in definitions and reference them with $ref. Note: this tool resolves local references but does not fetch external URLs.
{
"definitions": {
"address": {
"type": "object",
"required": ["line1", "city"],
"properties": {
"line1": { "type": "string" },
"city": { "type": "string" }
}
}
},
"type": "object",
"properties": {
"billing": { "$ref": "#/definitions/address" },
"shipping": { "$ref": "#/definitions/address" }
}
}
Tips and common mistakes
requiredchecks presence, not non-emptiness. A field set to"",null, or0still satisfiesrequired. Combine withminLengthortypeto enforce real values. Read more in the companion post: JSON Schema required keyword explained."type": "number"accepts integers. Use"type": "integer"if you specifically want whole numbers (e.g., IDs, counts).- Default values are documentation, not validation. The
defaultkeyword does not insert a value or change validation behaviour — it just tells readers what a sensible default is. - Regular expressions in
patternare unanchored."^foo$"matches only "foo";"foo"matches "foo", "foobar", "barfoo", etc. Always anchor patterns when you want exact-match. additionalProperties: falseonly checks the current object, not nested objects. Apply it at every level you want strict.- Test failure cases too. A schema that accepts everything is just as bug-prone as one that rejects valid input. Pick a sample above, then deliberately break it (change a type, remove a required field) and click Validate to see the error.
Frequently Asked Questions
What is JSON Schema validation?
JSON Schema validation checks whether a JSON document matches the rules described in a JSON Schema — required keys, types, enums, regex patterns, numeric bounds, and so on. It is the standard way to confirm that API requests, configuration files, or stored documents have the structure your code expects.
Which JSON Schema drafts does this validator support?
This tool uses Ajv 8, which supports drafts 06, 07, 2019-09, and 2020-12. The samples on this page use draft-07 (the most widely used) but you can declare a different $schema and Ajv will use the matching draft.
Is my JSON sent to a server?
No. Validation runs entirely in your browser using JavaScript. Your JSON and your schema never leave your device.
Why does my schema with $ref to another file not work?
This online tool does not fetch external $ref targets from the network. Inline your referenced schemas into a single document using definitions and local $ref like #/definitions/address.
What does the Path column in the error table mean?
The Path is a JSON Pointer to the exact location in your data where validation failed. /users/0/age means the age field inside the first item of the users array. An empty path (/) means the root of the document.
How is JSON Schema different from TypeScript types?
TypeScript types disappear at runtime — they check your code as you write it but cannot validate data coming in from the network or a file. JSON Schema validates real values at runtime, so it complements TypeScript: use TypeScript for compile-time safety, use JSON Schema at the boundary where untrusted data enters your system.