Almost every JSON error you will meet is one of nine things. The parser message rarely says which, because most parsers report the token they choked on rather than the mistake you made, and those are not the same. Below is each error, the message you are likely to see, and the edit that fixes it.
If you want to follow along, paste any of these into the JSON validator. It names the mistake and marks the line.
1. A trailing comma
{
"name": "ana",
"role": "admin",
}
The comma after the last property is legal in JavaScript and illegal in JSON. Most parsers report this at the closing brace, one line below the actual comma, which is why people stare at the brace and see nothing wrong with it.
Delete the comma. If you hit this constantly because you are hand editing config files, the JSON repair tool removes them and shows you every one it removed.
2. Single quotes
{ 'name': 'ana' }
JSON has one string syntax and it uses double quotes. Single quotes are a JavaScript habit. The fix is mechanical, and worth doing with a tool rather than by hand if the document is large, because a quote inside a string has to be escaped rather than swapped.
3. Unquoted keys
{ name: "ana" }
Object keys are strings, and strings are quoted. JavaScript object literals let you leave the quotes off, and that is where this always comes from: someone copied an object out of a source file and expected it to be JSON. It is not.
4. Comments
{
// the account owner
"name": "ana"
}
JSON has no comments. Douglas Crockford removed them deliberately, because
people were using them to carry parsing directives. Both // and /* */ are
errors. If the comments matter, keep them in a source file and generate the JSON
from it, or move the note into a real field such as "_comment".
5. NaN, Infinity and undefined
{ "score": NaN, "limit": Infinity }
None of these exist in JSON. There is no syntax for them at all, which is why
the error usually reads as an unexpected bare word. Python writes NaN and
Infinity when you dump floats without care, and JavaScript produces
undefined from a missing property.
You have to decide what they should become, because there is no lossless
answer. null is the usual choice, a string such as "NaN" is the other. The
repair tool picks null and lists the change separately from the punctuation
fixes, because this one changes your data rather than its spelling.
6. Wrong case keywords
{ "active": True, "deleted": NULL }
JSON keywords are lower case: true, false, null. True and None are
Python, NULL is SQL and C. A parser that says “unexpected token T” is telling
you the truth in the least useful way available.
7. A newline inside a string
{ "note": "first line
second line" }
A JSON string cannot span lines. The line break has to be written as \n
inside the string. This one is common when someone pastes multi line text into a
config by hand, and the resulting error often points at the next line, not at
the string that was left open.
8. Numbers JSON does not allow
{ "a": .5, "b": +1, "c": 007, "d": 1_000 }
Four separate rules. A number needs a digit before the decimal point, so .5 is
0.5. A leading plus is not allowed. A leading zero is not allowed, which is
what rejects 007. Digit separators are a language feature, not a JSON one.
9. An unclosed bracket
{
"user": {
"name": "ana"
}
The parser hits the end of the file and reports it there, so the message says something about line 200 of a 200 line document while the missing brace is on line 2. This is the error worth having a good tool for: the validator on this site reports the position of the bracket that was opened and never closed, rather than the end of the input.
The two errors that are not syntax errors
Two documents can be perfectly valid and still wrong.
A duplicate key parses fine. The specification allows it, and every parser you are likely to use keeps the last value and silently discards the earlier one, so data disappears with no error anywhere:
{ "region": "eu-west-1", "retries": 3, "region": "us-east-1" }
The validator reports duplicates as warnings with both line numbers, and still calls the document valid, because that is what the specification says it is.
A long integer also parses fine, and then loses precision the moment anything reads it into a double:
{ "id": 12345678901234567890 }
Read that with a typical JSON library and you get 12345678901234567000. The
tools here work on the token stream instead of parsing into a JavaScript value,
so the number survives formatting, minifying and comparison unchanged. That is
also why the diff tool will not call two twenty digit integers
equal just because they collapse onto the same floating point value.
Reading an error message properly
Two habits save most of the time people spend on this.
First, treat the reported position as where the parser gave up, not where you went wrong. A missing comma is reported at the next token, an unclosed bracket at the end of the file, a trailing comma at the closing brace.
Second, check the character before the reported position. In the large majority of cases the actual mistake is one token earlier than the complaint.
If you would rather not do either, paste the document into the validator and read the message, which names the construct that is wrong instead of quoting the token that could not be parsed.