JSON Schema · Draft 2020-12

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.

Validation runs in your browser Value constraints have their own toggle // and /* */ comments are supported Need to clean up JSON first? Open JSON Formatter →
Validation mode
JSON data ↔ JSON SchemaStructural validation against Draft 2020-12
Additional contract rules
A JSON dataThe instance being validated
Ready to validate
0 characters
B JSON SchemaDraft 2020-12 and local $ref
Ready to validate
0 characters
Ready to validate ⌘/Ctrl + Enter

Result

Your JSON Schema report will appear here

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.

Save comparison

We will create a long unique link that automatically stops working after 24 hours.

Who can open it

Saving happens only when you choose it. Both source JSON documents are encrypted on the server and deleted after expiry.

From zero to a working contract

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.

01

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.

instance

JSON instance

The concrete document, API response, or configuration being validated. It goes in the left editor.

schema

Schema

A JSON object or boolean that describes the allowed shape of the instance. It goes in the right editor.

keyword

Keyword

A standard rule such as type, properties, required, items, or oneOf. Each keyword applies to a particular kind of node.

dialect

Dialect / Draft

A version of the JSON Schema vocabulary. The URI in $schema tells tools how to interpret every other keyword.

02

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.
03

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.

  1. 01

    Define the purpose and Draft

    Choose one contract boundary — one API response, event, or configuration file — and add $schema for Draft 2020-12.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

04

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.

Object schema

An object of keywords

The main form: every keyword contributes a rule or annotation.

{"type":"string"}
Boolean schema

Allow everything or nothing

true accepts every instance and false rejects every instance. Useful inside items and additionalProperties.

true  /  false
Type union

Several allowed types

In 2020-12 a nullable value is normally expressed as an array of types, with no special nullable keyword.

{"type":["string","null"]}
Composition

Combine several schemas

allOf requires all branches, anyOf at least one, and oneOf exactly one under the complete standard.

{"oneOf":[{"type":"string"},{"type":"integer"}]}
Homogeneous array

A list of one item type

One items schema is applied to every array element.

{"type":"array","items":{"type":"string"}}
Tuple array

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}
05

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.

DialectStatusWhen to choose itWhat to remember
Draft 2020-12RecommendedNew standalone schemas and modern tooling.prefixItems for tuples, $defs, dynamicRef, and a clarified array model. This validator targets this draft.
Draft 2019-09ModernAn existing ecosystem is already fixed on 2019-09.$defs and unevaluatedProperties are present, but arrays predate the items/prefixItems split.
Draft-07Very commonOlder 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-04LegacyOnly to maintain an existing contract.Older URIs, id instead of $id, and other incompatibilities. Do not choose these for a new project.
OpenAPI 3.1Close to 2020-12The 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.
06

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.
07

$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.
08

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.
09

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 distinction
  • properties, required, patternProperties, additionalProperties
  • minProperties, maxProperties, dependentRequired
  • items, prefixItems, minItems, maxItems
  • contains, minContains, maxContains
  • boolean schemas, allOf, local $ref, and references into $defs

Checked structurally

  • anyOf — at least one structurally matching branch is selected
  • oneOf — 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 exact oneOf matching

Not checked yet

  • format (email, URI, date-time) and contentEncoding / contentMediaType / contentSchema
  • unevaluatedProperties, unevaluatedItems, dependentSchemas, propertyNames
  • $dynamicRef, custom vocabularies, and external network $ref
  • The tool loads nothing from the internet; bundle external schema dependencies into local $defs
10

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.