Validate JSON against JSON Schema
Paste JSON data on the left and a schema on the right to get a clickable report for structure, types, and required properties. A separate toggle enables enum, const, ranges, and other value constraints.
Result
Paste JSON and a schema or open the example. Click any result to jump to the related lines in both the data and the schema.
What JSON Schema is and how to build one correctly
JSON Schema is a machine-readable description of a JSON document shape: which nodes are objects or arrays, which fields are required, which types are allowed, and whether extra properties are accepted.
A schema is applied to a JSON instance. It is not a sample response and does not contain the “correct” data; it defines rules that let any future response be accepted or rejected.
Schema, instance, and keyword vocabulary
JSON Schema has three layers: the data, the rules, and the selected dialect of the standard. Keeping them separate makes even a large schema predictable.
instanceJSON instance
The concrete document, API response, or configuration being validated. It goes in the left editor.
schemaSchema
A JSON object or boolean that describes the allowed shape of the instance. It goes in the right editor.
keywordKeyword
A standard rule such as type, properties, required, items, or oneOf. Each keyword applies to a particular kind of node.
dialectDialect / Draft
A version of the JSON Schema vocabulary. The URI in $schema tells tools how to interpret every other keyword.
A minimal practical object schema
Start with the root type and narrow the contract gradually. properties describes known fields, while required separately says which fields must exist.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User",
"type": "object",
"required": ["id", "email"],
"additionalProperties": false,
"properties": {
"id": {"type": "integer"},
"email": {"type": "string"},
"roles": {
"type": "array",
"items": {"type": "string"}
}
}
}
$schema- The dialect URI. Draft 2020-12 is usually the right choice for new schemas.
$id- A stable schema identifier and a base for resolving references. It does not have to match the file URL.
type- An allowed JSON type: object, array, string, number, integer, boolean, or null.
properties- A map of schemas for known object properties. Listing a property here does not make it required.
required- An array of property names that must exist in an object.
additionalProperties- false rejects unknown fields; a schema validates them; true allows all of them.
How to derive a schema from existing JSON
Automatic generation only produces a draft: one example cannot reveal what is required, nullable, or allowed to vary. A dependable schema takes six passes.
- 01
Define the purpose and Draft
Choose one contract boundary — one API response, event, or configuration file — and add $schema for Draft 2020-12.
- 02
Mark the type of every node
An object gets type: object and properties, an array gets type: array, and primitives use string, number, integer, boolean, or null.
- 03
Separate known from required fields
Move known fields into properties, but put only truly mandatory fields into required. A single sample cannot prove that a field is required.
- 04
Choose an extension policy
additionalProperties: false is useful for closed internal contracts. Public APIs often need to tolerate new fields so consumers survive compatible evolution.
- 05
Model arrays and alternatives
Use items for a homogeneous list and prefixItems for a tuple with different positions. Express alternative shapes with anyOf or oneOf.
- 06
Extract repetition and test real samples
Move repeated fragments into $defs and reuse them through local $ref. Then run both valid and deliberately invalid instances to tune strictness.
The different forms a JSON Schema can take
A schema is not always a large object with properties. The standard also supports boolean schemas, type unions, composition, and multiple array models.
An object of keywords
The main form: every keyword contributes a rule or annotation.
{"type":"string"}Allow everything or nothing
true accepts every instance and false rejects every instance. Useful inside items and additionalProperties.
true / falseSeveral allowed types
In 2020-12 a nullable value is normally expressed as an array of types, with no special nullable keyword.
{"type":["string","null"]}Combine several schemas
allOf requires all branches, anyOf at least one, and oneOf exactly one under the complete standard.
{"oneOf":[{"type":"string"},{"type":"integer"}]}A list of one item type
One items schema is applied to every array element.
{"type":"array","items":{"type":"string"}}A tuple by position
prefixItems assigns a schema to each position; items describes or forbids the remaining tail.
{"prefixItems":[{"type":"string"},{"type":"integer"}],"items":false}JSON Schema versions: Draft 2020-12, 2019-09, 07, and OpenAPI
A Draft is the version of the schema language, not the version of your document. Avoid mixing syntax from different drafts: tuple arrays and reusable definitions differ in particular.
| Dialect | Status | When to choose it | What to remember |
|---|---|---|---|
| Draft 2020-12 | Recommended | New standalone schemas and modern tooling. | prefixItems for tuples, $defs, dynamicRef, and a clarified array model. This validator targets this draft. |
| Draft 2019-09 | Modern | An existing ecosystem is already fixed on 2019-09. | $defs and unevaluatedProperties are present, but arrays predate the items/prefixItems split. |
| Draft-07 | Very common | Older APIs, code generators, and libraries without 2020-12. | Definitions often live in definitions and a tuple is an array inside items. Migration requires conversion. |
| Draft-06 / Draft-04 | Legacy | Only to maintain an existing contract. | Older URIs, id instead of $id, and other incompatibilities. Do not choose these for a new project. |
| OpenAPI 3.1 | Close to 2020-12 | The schema is part of an OpenAPI document. | OAS 3.1 uses a JSON Schema 2020-12 dialect with the OpenAPI vocabulary. OAS 3.0 is an older incompatible subset with nullable. |
items, prefixItems, and contains
First decide whether the array is a list of similar entities or a tuple of fixed positions. These are different contracts.
{
"type": "array",
"prefixItems": [
{"type": "string"},
{"type": "integer"}
],
"items": false,
"minItems": 2,
"maxItems": 2
}
- items with a schema object validates every element of a homogeneous list.
- prefixItems describes positions 0, 1, 2…; items applies to the remaining tail.
- contains requires some elements to match a separate schema; minContains and maxContains control the count.
$defs and local $ref
Repeated fragments should live in one place. $defs is an ordinary container of schemas and $ref points to them using a JSON Pointer.
{
"$defs": {
"id": {"type": "integer"}
},
"type": "object",
"properties": {
"userId": {"$ref": "#/$defs/id"},
"teamId": {"$ref": "#/$defs/id"}
}
}
- # denotes the current schema root; #/$defs/id is a local JSON Pointer.
- Path segments containing / or ~ are escaped as ~1 and ~0.
- This tool never fetches external $ref URLs: data stays in the browser and only local references are supported.
allOf, anyOf, and oneOf
Composition combines complete schemas. Pick the operator from its logical meaning, not as a substitute for object inheritance.
{
"oneOf": [
{
"type": "object",
"required": ["email"],
"properties": {"email": {"type": "string"}}
},
{
"type": "object",
"required": ["phone"],
"properties": {"phone": {"type": "string"}}
}
]
}
allOfThe instance must pass every branch. This is an intersection of rules, not inheritance that automatically merges properties.anyOfAt least one branch must match. Several branches may match at the same time.oneOfThe standard requires exactly one matching branch. Without value checks the closest structural branch is selected; with the toggle on, exactly one complete match is enforced.
What this validator actually checks
JSON Schema is a large standard. This is the exact current algorithm coverage and how the value toggle changes it.
Fully checked
type, including type unions and the number / integer distinctionproperties,required,patternProperties,additionalPropertiesminProperties,maxProperties,dependentRequireditems,prefixItems,minItems,maxItemscontains,minContains,maxContains- boolean schemas,
allOf, local$ref, and references into$defs
Checked structurally
anyOf— at least one structurally matching branch is selectedoneOf— without value checks, the closest structural branch is selected- Property and item order — an extra tool option, not a standard JSON Schema rule
$schema,$id, title, description, default, and examples are annotations and do not affect the result
With the “Check values” toggle
- Concrete values:
enum,const - Strings:
pattern,minLength,maxLength - Numbers:
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf uniqueItems,not,if/then/else, and exactoneOfmatching
Not checked yet
format(email, URI, date-time) and contentEncoding / contentMediaType / contentSchemaunevaluatedProperties,unevaluatedItems,dependentSchemas,propertyNames$dynamicRef, custom vocabularies, and external network$ref- The tool loads nothing from the internet; bundle external schema dependencies into local
$defs
Frequently asked questions
Short answers to choices that most often make a schema either too strict or too weak to be useful.
Does properties make fields required?
No. properties only defines rules for a field when it exists. Required names are listed separately in required on the parent object.
Should I always set additionalProperties: false?
No. It helps with a closed contract, but can break consumers of a public API when harmless fields are added. Choose an evolution policy deliberately.
How do I allow string or null?
In Draft 2020-12 use type: ["string", "null"]. nullable mainly belongs to OpenAPI 3.0 and is not a standard JSON Schema keyword.
What is the difference between integer and number?
integer accepts only numbers without a fractional part, while number accepts both integers and decimals. JSON has no separate 32-bit or 64-bit numeric types.
Can I generate a schema automatically from one example?
You can get a draft of types and nesting, but cannot reliably infer required fields, nullability, alternatives, or the extra-property policy. Those need contract knowledge.
Why does the validator accept an invalid email or enum value?
enum is checked after you enable “Check values.” format, including email, is not checked yet; use pattern or a full standards validator when format validation is mandatory.