ToolzYard Blog

Developer guides and tutorials

JSON Validation Guide

How to Validate JSON and Fix Common Syntax Errors

Published: March 9, 2026 • Updated: July 10, 2026 • By , Founder of ThreeWorks

"Is this JSON valid?" is really two questions wearing one coat. The first: will a parser accept it without throwing? The second: is it the right JSON — the shape, fields, and types your code actually expects? A document can sail through the first check and be completely broken for your purposes. Confusing these two layers is why "the JSON was valid" and "the request still failed" end up in the same bug report. This guide separates them and covers what real validation catches at each level.

To check a document as you read, keep the ToolzYard JSON Validator open. It reports the exact position where parsing breaks, which is the first thing the rest of this guide will teach you to read.

The two layers of "valid"

There are two distinct kinds of JSON validity, and good tooling checks them separately:

  • Syntactic validity — the bytes conform to the RFC 8259 grammar, so a parser accepts them. This is what JSON.parse and a plain validator check.
  • Schema validity — the parsed data matches an expected structure: required fields present, types correct, values in range. This needs JSON Schema, not just a parser.

The trap is that syntactic validity is necessary but nowhere near sufficient. {"age": "twelve"} is perfectly valid JSON and a disaster if your code expects age to be a number. Most "valid JSON that still broke everything" bugs live in this gap.

What a parse error actually tells you

When syntactic validation fails, the message is more precise than it looks. A typical error — Unexpected token } in JSON at position 47 — names a character offset from the start of the document, not a line number. That is why a validator that maps the offset to a line and column and highlights it saves so much time on a minified one-liner, where "position 47" is otherwise meaningless.

Two habits make parse errors quick to fix. First, always fix the first error and re-check: a single missing comma or quote throws the parser off, and much of what it reports after that is noise caused by the one real mistake. Second, learn the vocabulary — Unexpected end of JSON input almost always means an unclosed brace or bracket (the parser hit end-of-file still waiting for a closing symbol), while Unexpected token means it found a character that cannot legally appear where it did, such as a stray comma or an unquoted word.

The four errors behind almost every parse failure

Syntactically invalid JSON nearly always fails for one of four reasons, and three of them share a root cause: the text was written as a JavaScript object literal, which is a looser grammar than JSON.

  • Single quotes. JSON requires double quotes for both keys and string values. {'name': 'John'} is a valid JavaScript object and invalid JSON.
  • Unquoted keys. {name: "John"} is likewise legal JavaScript, illegal JSON. Every key must be a double-quoted string.
  • A trailing comma after the final element of an object or array. JavaScript has allowed these for years and most linters encourage them, which is exactly why the habit leaks into JSON, where they are forbidden.
  • An unescaped control character inside a string — most often a raw newline or tab pasted from a terminal. Inside a JSON string these must be written as \n and \t. This is the one error that does not come from JavaScript syntax, and the one a JSON escaper exists to fix.

Notice what is not on that list: comments. JSON has no comment syntax at all. A // or /* */ that survived a copy-paste from a config file is a parse error, not a stylistic wrinkle. Formats like JSON5 and JSONC add comments and trailing commas back, but a strict validator — the kind an API uses — rejects all of it.

Valid JSON that is still wrong

This is the half of validation that catches people, because the parser stays silent. The following are all syntactically valid and can still break your program.

Large integers lose precision. JavaScript parses every JSON number into an IEEE-754 double, which represents integers exactly only up to 253 − 1 (9007199254740991). A 64-bit database ID or a Twitter/X snowflake above that silently rounds the moment JSON.parse touches it — no error, just a wrong number. A validator that only checks syntax will pass it. The fix belongs on the producing side: send large IDs as strings.

Duplicate keys are not an error. RFC 8259 says a duplicate name within an object produces undefined behaviour, not a rejection. {"role":"user","role":"admin"} parses cleanly, and JSON.parse keeps the last value — so a document that looks like it grants user access actually grants admin. Most validators stay quiet about this; the ones worth using warn.

A byte-order mark breaks the first key. A file saved as "UTF-8 with BOM" begins with the invisible bytes EF BB BF. Some parsers reject the document outright; others parse it but leave the mark stuck to the front of the first key, so data["name"] mysteriously returns undefined while the key looks correct in your editor.

The schema is the whole point. {"age": "twelve"} is valid JSON and a disaster if age is supposed to be a number. Catching that requires JSON Schema — a separate document that declares required fields, types, and ranges, checked by a validator such as Ajv. Syntactic validation asks "can this be parsed?"; schema validation asks "is this the data I expected?" Production systems need both.

Validating large payloads without loading them whole

A multi-megabyte export will freeze a browser-based validator, because tools like JSON.parse build the entire object graph in memory before returning. Past a few hundred megabytes you may exceed the runtime's string or heap limit and get a crash rather than an error message.

The answer is a streaming parser that reads the document as a sequence of tokens without holding all of it at once — jq on the command line, or a SAX-style library such as stream-json in Node or ijson in Python. For a quick check of a huge file, jq empty bigfile.json validates the whole thing and prints only the first syntax error, using a fraction of the memory a full parse would need. Reach for an in-browser validator when the payload is something you can comfortably read; reach for a streaming tool when it is something you can only sample.

ToolzYard tools to help

Conclusion

Validating JSON is one of the easiest ways to prevent broken payloads, parsing errors, and debugging headaches. Because JSON is strict, even small mistakes like single quotes, missing commas, or unclosed brackets can make the entire document invalid.

The good news is that most JSON errors are simple to fix once you know what to look for. Validate first, read the error carefully, fix the syntax, and then format the JSON for better readability. That workflow works well whether you are dealing with APIs, config files, app data, or testing payloads.

Frequently Asked Questions

My JSON parses fine but my program still breaks. Is the JSON valid?

Syntactically, yes — but syntactic validity only means a parser accepts it. If your code expects age to be a number and the document has "age": "twelve", that is valid JSON and still wrong for you. Catching that needs schema validation (JSON Schema), which checks required fields, types, and ranges, not just grammar.

Why did my large ID number change after parsing?

JavaScript parses JSON numbers as IEEE-754 doubles, which hold integers exactly only up to 253 − 1 (9007199254740991). Anything larger — a 64-bit database key, a snowflake ID — is silently rounded by JSON.parse with no error. The fix is on the producing side: send such values as strings.

Is a JSON object with two identical keys invalid?

No. RFC 8259 makes duplicate keys undefined behaviour rather than an error, so it parses. JSON.parse keeps the last occurrence, which can quietly change meaning — an object that appears to set "role":"user" may end on "role":"admin". A good validator warns about duplicates even though the spec does not require rejection.

Why does my first key come back as undefined?

Usually a byte-order mark. A file saved as "UTF-8 with BOM" starts with invisible bytes (EF BB BF) that some parsers leave attached to the first key, so the key looks correct in your editor but does not match a normal string lookup. Save as UTF-8 without a BOM.

Are comments allowed in JSON?

No. Standard JSON has no comment syntax; a // or /* */ is a parse error. JSON5 and JSONC add comments and trailing commas, but strict parsers — including the ones most APIs use — reject them.