JSON Explained: What It Is, Why It Breaks, and How to Fix It
JSON runs the modern web, but a single misplaced comma can break an entire file. Here is what JSON is, the handful of rules it enforces, and why your file refuses to parse.
If you have worked with web APIs, configuration files, or modern apps, you have run into JSON — and probably into a JSON error that stopped everything over what looked like nothing. JSON is simultaneously the most widely used data format on the web and one of the strictest, which is exactly why a single stray character can make a whole file unreadable. Understanding its small set of rules makes those errors quick to spot and fix.
What JSON is
JSON stands for JavaScript Object Notation. It is a text format for representing structured data — objects with named fields, lists of items, numbers, text, and true/false values — in a way that is both human-readable and easy for programs to parse. Despite the name it is language-independent; virtually every programming language can read and write it, which is why it became the default way for systems to exchange data over the internet.
A JSON object is wrapped in curly braces and holds key–value pairs: {"name": "Ada", "age": 36, "active": true}. An array is wrapped in square brackets and holds an ordered list: ["red", "green", "blue"]. Values can themselves be objects or arrays, so JSON can describe deeply nested structures.
The rules it enforces
JSON's strictness is the source of both its reliability and its frustration. Keys must be wrapped in double quotes — not single quotes, and not left bare. Text values must also use double quotes. Numbers are written plainly, without quotes. The only permitted values are objects, arrays, strings, numbers, true, false, and null — no dates, no functions, no comments.
Crucially, JSON does not allow a trailing comma after the last item in an object or array. This is the single most common thing that breaks otherwise-valid JSON, because many programming languages do allow it, so the habit carries over.
The absence of comments deserves its own mention, because it surprises people constantly. There is no way to annotate a JSON file — no // and no /* */. This was a deliberate decision by Douglas Crockford, who specified the format: he had seen comments abused to carry parsing directives, and removing them kept JSON a pure data format. It is a defensible choice that is nonetheless a daily irritation for anyone using JSON as a configuration file, and it is the main reason formats like YAML and TOML exist for config work.
The errors that trip people up most
Four mistakes account for most JSON failures. First, the trailing comma: {"a": 1, "b": 2,} is invalid — delete that last comma. Second, single quotes: {'name': 'Ada'} must become {"name": "Ada"}. Third, unquoted keys: {name: "Ada"} needs quotes around name. Fourth, mismatched or missing brackets and braces — an opening { or [ without its matching close, which is easy to do in large nested files.
Less common but baffling when they happen: an unescaped double quote inside a string (you need a backslash, like "she said \"hi\""), and "smart quotes" pasted from a word processor, which look like quotes but are different characters JSON does not accept.
How to read a parse error
JSON parsers usually report the line and column where parsing failed — but the real problem is often just before that point. A missing comma, for instance, is only detected when the parser reaches the next token and finds it unexpected. So when an error points at line 12, scan the end of line 11 too. Once you know the four common culprits, most errors take seconds to locate.
Two error messages are worth learning to translate on sight. "Unexpected end of input" almost always means an unclosed bracket or brace — the parser reached the end of the file still waiting for something to close. And "Unexpected token < in JSON at position 0" is not a JSON problem at all: it means you asked for JSON and received HTML, typically an error page or a login redirect. When you see that one, stop debugging the parser and go look at what the server actually returned.
The number trap that silently corrupts data
This is the JSON problem that does real damage, because it does not throw an error — it quietly changes your data.
JSON itself places no limit on the size or precision of a number. JavaScript does. Every number in JavaScript is a 64-bit floating-point value, which can represent integers exactly only up to about 9 quadrillion (2^53 − 1, or 9,007,199,254,740,991). Parse a JSON number larger than that in a browser and you get back a value that is close to the original but not equal to it. No warning, no exception, just a wrong number.
Where this bites is identifiers. Large database IDs, Twitter/X post IDs, Discord snowflakes and similar 64-bit values routinely exceed the safe range, and the last few digits get rounded away — so your code fetches the wrong record, or an ID no longer matches itself after a round trip. This is why well-designed APIs transmit large identifiers as strings: {"id": "9007199254740993"} survives intact, while {"id": 9007199254740993} may not.
The same category of problem applies to money. Never store currency as a JSON floating-point number: 0.1 + 0.2 does not equal 0.3 in binary floating point, and financial totals accumulate the error. Use integer minor units (cents) or a decimal string.
What JSON deliberately leaves out
JSON has no date type. This surprises people, because dates are everywhere in real data. The universal convention is to encode them as ISO 8601 strings — "2026-07-29T14:30:00Z" — which sorts correctly as plain text and is unambiguous about the timezone. Anything else, and especially a locale-specific format like "07/08/2026", will eventually be misread by someone on the other side of an ocean.
JSON also has no binary type. Files and images are usually Base64-encoded into a string, which inflates the size by roughly a third and is why large binaries are normally sent alongside JSON rather than inside it.
And JSON does not guarantee key order or forbid duplicate keys. The specification says object members are unordered; most parsers preserve insertion order in practice, but relying on it is fragile. If a key appears twice, most parsers silently take the last one — a good way to lose data without noticing.
JSON Lines, and files too big to parse
A standard JSON file has to be read in its entirety before any of it can be used, because the parser cannot know the document is valid until it reaches the closing bracket. For a multi-gigabyte export, that means loading the whole thing into memory.
The usual answer is JSON Lines (also called NDJSON): one complete JSON object per line, no wrapping array, no commas between records. It is not valid JSON as a whole document, but each line is, so a program can process records one at a time with constant memory, and a crash halfway through leaves everything up to that point usable. It is the default for log files, data exports and streaming pipelines.
If you need to enforce structure rather than just syntax — required fields, value types, permitted ranges — that is what JSON Schema is for. It lets you describe the shape a document must take and validate against it, which catches the large class of files that parse perfectly and are still wrong.
Validate and format it instantly
Rather than hunting through a wall of minified text by eye, paste it into QTNest's JSON Validator & Formatter. It pinpoints the exact location of a syntax error in validate mode, and in format mode it pretty-prints valid JSON with your choice of indentation so the structure becomes readable. Everything runs in your browser, so even sensitive payloads with keys or personal data never leave your device.