JSON Validation

How to validate JSON: the difference between syntax validation and schema validation, when you need JSON Schema, and how to validate JSON in code and CI.

7 min read

Two different questions

"Validate this JSON" means one of two quite different things, and confusing them wastes a lot of time.

Syntax validation asks: is this well-formed JSON? Are the quotes double, the commas in the right places, the brackets balanced? This is what a parser does, and what a formatter does implicitly — it must parse before it can print.

Schema validation asks: is this the data I expected? Are the required fields present, are the types right, is age a non-negative integer, is email actually an email address?

A document can pass the first and fail the second completely:

{
  "id": "not-a-number",
  "email": "definitely not an email",
  "age": -47
}

That is flawless JSON. It is also useless as a user record. Syntax validation will not tell you so.

Syntax validation

The fastest syntax check is to format the document: a formatter parses first, so malformed input produces an error rather than output.

Validate your JSON now →

In code, syntax validation is a try/catch around the parser:

function isValidJson(text) {
  try { JSON.parse(text); return true; }
  catch { return false; }
}
import json

def is_valid_json(text: str) -> bool:
    try:
        json.loads(text)
        return True
    except json.JSONDecodeError:
        return False
jq empty file.json && echo "valid"
python -m json.tool file.json > /dev/null && echo "valid"

Validate against RFC 8259, the current Internet Standard, aligned with ECMA-404. It supersedes RFC 4627 and RFC 7159; the practical difference is that any well-formed value — not only objects and arrays — is valid at the top level.

Schema validation

JSON Schema is the standard vocabulary for describing the shape of a JSON document. A schema is itself JSON:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["id", "email"],
  "additionalProperties": false,
  "properties": {
    "id":    { "type": "integer", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "age":   { "type": "integer", "minimum": 0, "maximum": 150 },
    "roles": {
      "type": "array",
      "items": { "enum": ["admin", "editor", "viewer"] },
      "uniqueItems": true
    }
  }
}

That schema rejects the broken record above on three separate counts: id is not an integer, email fails the format check, and age is below the minimum.

additionalProperties: false is worth calling out — without it, a schema accepts any extra fields silently, which hides typos. "emial" passes happily unless you forbid unknown properties.

Validating against a schema in code

// Node — Ajv is the de facto standard validator
import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = new Ajv({ allErrors: true });
addFormats(ajv);                 // "email", "date-time", "uri", ...

const validate = ajv.compile(schema);
if (!validate(data)) console.error(validate.errors);
from jsonschema import validate, ValidationError

try:
    validate(instance=data, schema=schema)
except ValidationError as e:
    print(f"{list(e.absolute_path)}: {e.message}")

Note allErrors: true in the Ajv example — by default it stops at the first failure, which makes for a frustrating debugging loop when several fields are wrong.

When schema validation is worth it

It has a real cost: a schema is another artefact to write, review, and keep in sync. It pays for itself when data crosses a boundary you do not control.

Worth it for: public API request bodies, third-party webhooks, user-supplied configuration files, CI checks on data files, and generating documentation or types from one source of truth.

Usually not worth it for: internal data you produce and consume within one service, one-off scripts, or anything where your language's own type system already covers you.

An honest middle ground for TypeScript projects: runtime validators such as Zod or Valibot give you validation and a static type from a single declaration, without the ceremony of a separate schema file. Use JSON Schema when the contract must be language-neutral and published; use a runtime validator when it only needs to hold inside one codebase.

Validation in CI

Catching malformed JSON before merge is cheap:

# Fail the build if any tracked JSON file is malformed
find . -name "*.json" -not -path "./node_modules/*" \
  -exec sh -c 'jq empty "$1" || { echo "INVALID: $1"; exit 1; }' _ {} \;

For schema conformance, ajv-cli validates data files against a schema as a build step:

npx ajv validate -s schema.json -d "data/*.json" --all-errors

Add either as a pre-commit hook and malformed JSON stops reaching the repository at all.

A note on privacy

Validation requires reading the document, so where it happens matters. A client-side validator parses in your browser and transmits nothing. A server-side one uploads your document to a machine you do not control — which may log it.

If you are validating an API response containing tokens or personal data, use a tool that states clearly it is client-side. Our formatter runs entirely in the browser via the native JSON.parse; nothing is uploaded, logged, or stored. As general hygiene, still rotate any live credential that has passed through a third-party tool.

Related

Frequently asked questions

What is the difference between validating JSON syntax and JSON Schema?

Syntax validation answers "is this well-formed JSON?" — are the quotes, commas, and brackets correct. Schema validation answers "is this the right data?" — are the required fields present, are the types correct, are the values within permitted ranges. A document can be perfectly valid JSON and still be entirely wrong for its purpose, which is what JSON Schema exists to catch.

Do I need JSON Schema for a small project?

Usually not. For internal data you control end to end, a syntax check plus your language's own type system is normally enough. JSON Schema earns its cost when data crosses a boundary you do not control — a public API, third-party webhooks, user-uploaded configuration — or when you want machine-generated documentation and types from a single source of truth.

Is JSON validation safe to do in a browser tool?

It depends entirely on whether the tool sends your data anywhere. A client-side validator parses in your browser and transmits nothing, which is safe for sensitive payloads. A server-side validator uploads your document to someone else's machine. Check before pasting anything containing tokens or personal data — and as a general rule, rotate any credential that has been through a third-party tool.

Which JSON specification should I validate against?

RFC 8259, the current IETF Internet Standard, which is semantically aligned with ECMA-404. It supersedes RFC 4627 and RFC 7159. The practical difference from RFC 4627 is that any well-formed JSON value is valid at the top level, not just objects and arrays.

More in JSON Guide

← Back to JSON Guide