Skip to content
Back to Blog
By JSONConvert Team··5 min read

JSON Schema Validation Explained

You call an external API and your code assumes the response has a data.user.id field. It usually does. Then one day it comes back as a string instead of an integer, or the field is missing because the user deleted their account. JSON Schema lets you define exactly what valid data looks like and catch these mismatches before they reach your application logic.

What JSON Schema Is (and Isn't)

JSON Schema is a vocabulary for annotating and validating JSON documents. It is not a library - it is a specification (currently draft 2020-12) that multiple validators implement. You write the schema once as a JSON document, and any compliant tool uses it to check data.

The minimal schema looks like this:

This says: the value must be an object with three required fields - id as an integer, name as a string, and email as a string. Properties not listed here are allowed by default.

Core Keywords

Most validation work uses fewer than a dozen keywords:

KeywordWhat it does
typeRestricts to string, number, integer, boolean, array, object, or null
requiredArray of property names that must be present
propertiesDefines sub-schemas for named properties
itemsSchema applied to every element in an array
minLength / maxLengthString length bounds
minimum / maximumNumeric range constraints
enumRestricts value to a fixed list: ["active", "inactive"]
patternRegex constraint on a string value
additionalPropertiesWhen false, blocks any property not listed in properties
$refReferences another schema by URI or local anchor
One type distinction worth knowing: "integer" and "number" are separate types. 3.0 satisfies "number" but not "integer". Use "integer" only when you strictly need whole numbers.

Validating a Real API Response

Here is a realistic user object from an API:

A schema that captures the real shape of this data:

Two things worth noting. First, email is not in required and uses "type": ["string", "null"]. APIs commonly return null for optional profile fields, and a schema that only allows "string" will reject valid responses. Second, plan is not required at the top level - if it is absent, the schema passes. If it is present, its properties are validated against the nested schema.

Using $ref to Avoid Repetition

When the same sub-schema appears in multiple places, $ref prevents duplication. The $defs keyword defines reusable schemas locally within the same document:

Both address fields share one definition. Update address once and both references reflect the change. This pattern is the same one OpenAPI 3.x uses under components/schemas.

Validate Without Installing Anything

For quick checks - during schema design, in code review, or while debugging a failing API response - you do not need to install ajv or wire up a validation pipeline. The JSON validator lets you paste a payload and check it instantly against your schema in the browser.

For generating a schema from scratch, the faster approach is to start from a real response rather than writing one by hand. The JSON Schema generator infers types and required fields from a sample payload in one click. You then layer in constraints like minimum, enum, and pattern manually. The JSON beautifier is useful for cleaning up the generated schema before sharing it with a team.

Three Common Mistakes

The most frequent schema bug is not accounting for nullable fields. API documentation often describes a field as a string when the real response can return null for unset values. Use "type": ["string", "null"] for any field that could be absent or empty. Checking real responses - not just the docs - is the only reliable way to catch this.

additionalProperties: false is stricter than it looks. It rejects any property not listed in properties, which will break your validation when the API adds a new field in a minor version update. Leave it off unless you are enforcing a strict contract on both sides of the interface.

The third issue is draft version confusion. The nullable keyword from OpenAPI 3.0 does not exist in core JSON Schema - it is an extension. If your schema runs through a standard validator, use "type": ["string", "null"] instead of nullable: true.

Start Permissive, Then Tighten

The most productive workflow: generate an initial schema from a real response, validate it against several actual payloads, then add constraints as you learn the data's real shape. Starting with a strict schema and debugging errors on real data takes longer and tends to produce schemas with subtle wrong assumptions baked in.

Generate a first draft with the JSON Schema generator, test payloads with the JSON validator, and tighten from there.

Related Tools