Guides

How to Validate JSON Against a Schema

Marcus BrennanΒ·Β·9 min read

A config file passed JSON.parse without a complaint and still took a service down at two in the morning. The file was flawless JSON β€” every brace matched, every string quoted. It just had "maxConnections": "100" where the code expected a number, and a retry limit of -1 that an unguarded loop happily treated as β€œretry forever.” The parser had no objection to any of it, because none of it was a syntax problem. It was a shape problem, and JSON parsing doesn't check shape.

That gap β€” between JSON that parses and JSON that's actually correct β€” is exactly what schema validation closes. Here's how it works, and how to set it up so the next malformed payload gets rejected at the door with a clear message instead of detonating three layers deep.

Valid is not the same as correct

When people say a JSON document is β€œvalid,” they almost always mean it parsed. That's a real check, and if you're chasing a parse error our guide on fixing invalid JSON is the place to start. But parsing only confirms the punctuation is legal.

It confirms nothing about whether the port is a number, whether the required apiKey field is even present, or whether role is one of the three values your code can handle. {"port": "three thousand", "role": "wizard"} is impeccable JSON and useless to a program that expects an integer port and a role of admin, editor, or viewer. Running it through a JSON validator will tell you the syntax is fine β€” which is the point where you need a second, stricter check.

A schema is a building inspection

Here's the mental model. Passing the parser is like confirming a building is made of real materials assembled into walls and a roof β€” it's a structure, not a pile of rubble. Passing a schema is the building inspector showing up with the code book: are there enough exits, is the wiring the right gauge, is the railing at the required height? Both matter. The first says β€œthis is a building.” The second says β€œthis building is safe to occupy.”

A JSON Schema is that code book, written down. And the neat part is that the code book is itself a JSON document β€” a file that describes what other JSON files must look like. You store it, version it, and share it like any other artifact.

Writing a minimal schema

You don't need the whole specification to get value. A handful of keywords covers the majority of real checks. Here's a schema for a small config object:

{
  "type": "object",
  "required": ["port", "role"],
  "properties": {
    "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
    "role": { "type": "string", "enum": ["admin", "editor", "viewer"] },
    "maxConnections": { "type": "integer", "minimum": 1 }
  }
}

Read it in plain English and it's obvious: the document must be an object; port and role must be present; port is an integer in the legal port range; role must be one of three exact strings; and maxConnections, if given, is a positive integer. That single schema would have caught both bugs from the opening story β€” the string port and the negative retry limit β€” before the file was ever loaded.

The workhorse keywords are type (the value's kind), properties (the shape of each field), required (what must be present), enum (a fixed set of allowed values), and the range constraints minimum, maximum, minLength, and maxLength. That's enough for most configs and API payloads.

Validating against it

With a schema written, validation is mechanical: hand a validator the schema and the document, and it reports every mismatch β€” the missing required field, the wrong type, the value outside the enum β€” usually with a path pointing at the offending property. Paste both into our JSON Schema Validator and it lists the failures instead of stopping at the first one, so you fix the whole document in a pass rather than one error per run.

If writing the schema from a blank page feels like a chore, don't. Start from a known-good sample: feed a representative document to the JSON Schema Generator, let it infer the types and structure, and then tighten the result β€” add the required list, swap loose strings for enums, set the numeric ranges. Generating first and refining second turns a from-scratch task into an editing one.

Validate at the boundary, not in the middle

The last piece is where this check runs. The rule that saves the most pain: validate at the boundary where data enters your system, and refuse anything that fails before it travels any further.

For an API, that's the incoming request body β€” reject a bad payload with a 400 and a clear message naming the field, rather than letting it flow inward and blow up in business logic that assumed it was clean. For an app, it's the config read at startup β€” fail loudly on boot, not at 2 a.m. under load. For a pipeline, it's a CI step that validates fixtures and sample payloads so a schema break is caught in review. Before validating, it helps to format the JSON so the error paths line up with something readable.

Parsing tells you the JSON is a structure. A schema tells you it's the right structure. Put the second check at the door, and the malformed payload that would have found you at the worst possible hour gets turned away while you're awake to read the message.

Try the tools

Frequently Asked Questions

What does it mean to validate JSON against a schema?

It means checking that a JSON document not only parses but also matches an expected structure: the right properties are present, each value is the right type, required fields aren't missing, and constrained values fall in the allowed set. The expected structure is written as a JSON Schema, and a validator compares your document to it and reports every place they disagree.

What is the difference between valid JSON and correct JSON?

Valid JSON is purely about syntax β€” quotes, commas, and braces in the right places so a parser accepts it. Correct JSON is about meaning β€” the data has the fields and types your program actually needs. `{"port": "three thousand"}` is perfectly valid JSON and completely wrong if your app expects a number. Schema validation is what closes that gap.

What is a JSON Schema?

A JSON Schema is a JSON document that describes the shape of other JSON documents. It uses keywords like `type`, `properties`, `required`, and `enum` to declare what a valid instance looks like. Because the schema is itself JSON, you can store it, version it, and share it like any other file, and validators in every major language know how to apply it.

Where should JSON validation happen?

At every boundary where untrusted or external data enters your system: incoming API request bodies, configuration files read at startup, messages pulled off a queue, and fixtures in your test or CI pipeline. Validating at the edge means a bad payload is rejected immediately with a precise error, instead of causing a confusing failure somewhere deep in the code that assumed the data was fine.

Do I have to write a JSON Schema by hand?

No. The fastest start is to generate one from a representative sample document β€” a schema generator infers the types and structure β€” and then tighten it manually: mark fields required, add enums for fixed value sets, and set ranges. Generating first and refining second is far quicker than writing every keyword from a blank file.

MB

Marcus Brennan writes for CodeUtilityKit, where the team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.