JSONBeautify JSON Linter

JSON Schema Validation in 2026: AJV, Formats, and Where Validation Stops Helping

JSONBeautify — Free Online JSON Formatter, Validator & Minifier Guides · Updated 2026-10-12 · All guides

Validation is where JSON bugs go to die, and also where a class of silent ones is created by people who turn format on and assume it is enforced. Measured figures below; the rest is behaviour you can reproduce in ten minutes.

Adoption, pulled not remembered

Source: the npm downloads API. Window 2024-10-01 to 2024-10-30 against 2026-09-11 to 2026-10-10, pulled 2026-10-12.

PackageFirst 30 daysLast 30 daysChangeJob
ajv496.3M1.749B+252%JSON Schema validator
ajv-formats105.3M617.6M+487%Optional format keywords for AJV
jsonschema13.14M26.92M+105%Spec-compliance test suite (Python-origin)

Two honest caveats. ajv-formats is the companion package to ajv, so its installs are mostly a subset of AJV's — adding the two rows counts the same adoption twice, which the libraries page warns about for metapackages generally. And the fastest-growing row here is the format add-on growing 1.9× faster than the validator itself, which says a lot of people are discovering the default does not check formats.

The default is stricter than you think and looser than you hope

import Ajv2020 from 'ajv/dist/2020.js';
const ajv = new Ajv2020({ allErrors: true });           // strict mode by default
const validate = ajv.compile(schema);                   // compiles to JS — this is why it is fast
if (!validate(data)) console.log(validate.errors);      // instancePath, keyword, message
  • additionalProperties is not implied. A schema listing three properties accepts forty. Every "our API rejects unknown fields" claim needs the explicit keyword, and for objects whose keys are data ({"user-1": {...}}) you want propertyNames + additionalProperties: false at the right nesting level.
  • format is annotation-only unless you opt in. {"type":"string","format":"email"} passes not-an-email in AJV's default configuration. Add ajv-formats (fast, regex-based) or ajv-formats-2019, or ajv-formats with audit: true if you want violations reported without failing. Python's jsonschema behaves the same way for the same reason: format validation is explicitly not required by the specification.
  • type: "integer" accepts 1.0 in some dialects and not others, and JSON has no float type — 1.0 and 1 are the same number. If precision matters, it is a string in your schema.
  • required checks presence, not truthiness. {"name": ""} and {"email": null} are both valid under most hand-written schemas. Add "minLength": 1, or {"type": "string", "minLength": 1} — the null case needs type to exclude it.

Draft choice, briefly

Draft 2020-12 is the current recommendation: $defs replaces definitions, prefixItems/items split, $ref siblings finally allowed. Draft-07 remains the most common thing you will meet in the wild and is fine for closed systems. OpenAPI 3.1 uses full JSON Schema; OpenAPI 3.0 uses a dialect subset that a validator does not know about, and its nullable keyword is not JSON Schema at all — this is the single largest source of "the schema validated but the payload was wrong" reports in API shops.

Validate-or-crash, in practice

WherePolicyWhy
Ingress to your APIcompile once at boot, reject with 400 + instancePaththe crash is the feature; compile-once keeps it microsecond-cheap
CI, config filesvalidate and exit non-zeroa bad config that starts is worse than a deploy that stops
Third-party webhook payloadsvalidate and log, keep processingyou do not control the producer; a hard fail means a partner outage you own
Internal, one producer, same reposkip itschema drift is caught by the type checker and the test suite

The failure mode at boundaries is not "validation too strict" but validating after the transformation: JSON.parse has already destroyed a 19-digit ID (see hacks) and collapsed duplicate keys before any schema sees the object. No schema can express "this integer must survive a round-trip", because the damage is upstream of the format's type system.

Compiling once is the whole performance story

AJV compiles schemas to JavaScript; the cost is the compile, not the validation. Compiling per request is the mistake that gets "AJV is slow" posted online. allErrors: true is slower and usually worth it at an API boundary, because returning every field error in one response is better UX than four round-trips.

What this site does and does not do

The formatter validates syntax with strict JSON.parse — position-in-input errors and nothing else. Schema validation belongs in your runtime, not in a browser tab: a schema is a contract about a system, and a paste box has no idea what your system promises. Validate shapes here by eye, and ship ajv at the boundary where the bytes arrive.

See also: patterns and gotchas for the null/NaN/BOM class, and alternatives for formats that avoid the precision problems above entirely.

Developer Sponsor / Partner
Copied to clipboard!