There are two completely different questions hiding behind “is this JSON valid?”. The first is whether it parses at all. The second is whether it contains what your program expects. A document can sail through the first and fail catastrophically at the second.
Syntax validation
Syntax validation asks whether the text conforms to the JSON grammar. Every parser does this for free — the question is how usefully it reports failure.
Native error messages are unhelpful because they describe where the parser gave up, not where you made the mistake. A missing comma on line 12 is often reported at the start of line 13, and a byte offset is not a location a human can act on.
The JSON validator re-scans failing input to report a line, a column, the offending text and a plain-English cause: “Trailing comma before the closing bracket” rather than a position number.
The seven errors that cause almost everything
- Trailing comma.
{"a": 1,}. Legal in JavaScript, illegal in JSON. Most often introduced by deleting the last item of a list. - Single quotes.
{'a': 1}. Usually the result of pasting a Pythondictor a JavaScript object literal. - Unquoted keys.
{a: 1}. Same cause. - Comments.
// note. Copied from a VS Code settings file, which is JSONC, not JSON. - Wrong literals.
True,False,None,undefined,NaN. JSON hastrue,falseandnull, all lowercase. - Unterminated string. A quote opened and never closed — frequently because a Windows path ended in a single backslash, which escaped the closing quote.
- Missing comma. Two values adjacent with no separator, usually after a copy-paste that dropped a line.
Reading an error position
When you only have a byte offset, convert it. In a shell:
# What is at byte 582?
head -c 582 input.json | tail -c 60
# Which line is byte 582 on?
head -c 582 input.json | wc -lThen look at the *line before* the reported position as well. Parsers report where they noticed the problem, which is usually one token after where you caused it.
Schema validation
Once a document parses, the interesting question is whether it is the document you expected. JSON Schema answers that: which properties must exist, what types they hold, what ranges and formats are permitted.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "email"],
"properties": {
"id": { "type": "integer", "minimum": 1 },
"email": { "type": "string", "format": "email" },
"status": { "enum": ["active", "invited", "disabled"] }
}
}Paste a schema into the validator and it is checked locally in your browser, reporting each violation with the path that failed. If you do not have a schema yet, the schema generator will infer a first draft from a sample document — then add the enums and ranges by hand, because those cannot be inferred.
Validate at the boundary
The practical lesson from most JSON-related production incidents is not “validate more”, it is “validate at the edge”. Check the payload the moment it arrives — at the API gateway, at the queue consumer, at the file loader — and reject it there with a clear message.
A malformed document that gets three services deep before anyone notices produces a stack trace in the wrong place, and an on-call engineer reading it has no idea which upstream sent it.
Before you write the validation
Run a real sample through the analyzer first. It reports which fields are missing from some records, which are null a third of the time, and which change type between records. Those three findings are what your schema actually needs to describe — and they are usually not what the API documentation says.