JSON (JavaScript Object Notation) is a plain-text format for structured data. A JSON document is one value: an object in {}, an array in [], a string, a number, true, false or null, and objects and arrays can nest those values inside each other. The rules are short and strict: keys and strings use double quotes, and there are no comments and no trailing commas.
A complete example
{
"id": 7,
"name": "Ada Lovelace",
"active": true,
"manager": null,
"roles": ["admin", "billing"],
"address": {
"city": "London",
"country": "GB"
}
}
That covers every type JSON has. The outer value is an object; "id" holds a number, "name" a string, "active" a boolean, "manager" null, "roles" an array of strings, and "address" another object.
The six types
RFC 8259, the IETF standard (also STD 90), describes JSON as "a lightweight, text-based, language-independent data interchange format" with four primitive types and two structured ones.
| Type | Looks like | Notes |
|---|---|---|
| string | "hello" |
Double quotes only |
| number | 7, -3, 2e3 |
No leading zeros, no NaN or Infinity |
| boolean | true, false |
Lowercase |
| null | null |
Lowercase |
| object | {"key": value} |
Unordered name/value pairs |
| array | [value, value] |
Ordered list |
Each language maps these onto its own types. Python's json module, for example, turns an object into a dict, an array into a list, true into True and null into None. Numbers become int or float depending on whether they have a fractional part.
The syntax rules that catch people
JSON looks like a JavaScript object literal, and that's the trap. MDN puts it bluntly: "most of JavaScript is not JSON." These are the differences that produce parse errors:
- Keys must be double-quoted strings.
{name: "Ada"}is a valid JavaScript object and invalid JSON. Single quotes don't work either, for keys or values. I wrote up the history in why JSON requires double quotes. - Trailing commas fail.
[1, 2, 3,]won't parse. See why JSON doesn't allow trailing commas. - No comments. Neither
//nor/* */. If you need them for config files, can JSON have comments covers the workarounds and the formats that allow them. - Literals are lowercase. The spec says
true,falseandnullMUST be lowercase, soTrue(Python habit) andNULLfail. - Numbers are plain decimals. Leading zeros aren't allowed, so
07is invalid. A decimal point needs a digit after it, so1.is invalid.NaN,Infinityandundefineddon't exist.
Whitespace is free. Spaces, tabs, line feeds and carriage returns can sit around any of the six structural characters ([ ] { } : ,), which is why the same data can be minified onto one line or pretty-printed across fifty without changing its meaning.
Strings and escapes
A string is any Unicode text in double quotes. Three things must be escaped inside it: the double quote, the backslash, and the control characters U+0000 through U+001F, which includes a raw newline. The short escapes are \", \\, \/, \b, \f, \n, \r and \t. Anything else can be written as \u plus four hex digits. Characters outside the Basic Multilingual Plane take two of those: the RFC's own example writes the G clef (U+1D11E) as "𝄞".
Paste a multi-line log message into a JSON string without converting the line breaks to \n, and the parser stops at the first one.
A few things the spec leaves loose
Duplicate keys. Names in an object SHOULD be unique, not MUST. When they aren't, RFC 8259 says the behavior of the receiving software is "unpredictable," and many implementations keep only the last pair. So {"role": "user", "role": "admin"} parses, and most parsers hand you "admin".
Key order. An object is defined as "an unordered collection", so code that needs keys in a set order depends on its parser's habits.
Big numbers. JSON numbers have no size limit in the grammar, but the RFC notes that integers are only reliably interoperable in the range [-(2**53)+1, (2**53)-1], because most software stores numbers as IEEE 754 doubles. A long numeric database ID can come back changed. Why JSON.parse loses precision on large numbers shows what happens and how to avoid it.
Top-level values. A JSON text is "a serialized value", so 42 or "hello" on its own is a valid document. Older specs required an object or an array at the top, and you'll still find tools that assume that.
Where the format is defined
There are two matching standards. ECMA-404 (2nd edition, December 2017) defines only "the syntax of valid JSON texts." RFC 8259, published the same month, adds the rules for exchanging JSON: it MUST be UTF-8 between systems that aren't part of a closed ecosystem, it MUST NOT start with a byte order mark, and its media type is application/json. The original description at json.org traces the format to a subset of ECMA-262 3rd Edition from December 1999.
My take, and the catch
My take: treat the "SHOULD be unique" rule as a MUST in your own code. A duplicated key is almost always a merge mistake, and "last one wins" hides it when it should fail loudly.
JSON's real limitation is how little it can say. Dates travel as strings because there is no date type, and every API picks its own convention. Without comments, it makes a poor hand-edited config file. Numbers carry no hint about precision. It's easy to parse because it leaves all of that to you.
When a document won't parse, a JSON validator shows the parser's error message, which usually points straight at one of the rules above.
FAQ
What does JSON stand for?
JavaScript Object Notation. It grew out of JavaScript syntax but is a separate, language-independent format, and most JavaScript is not valid JSON.
What data types does JSON support?
Six: string, number, boolean (true or false), null, object and array. There is no date, undefined, comment or binary type.
Can a JSON file be just a number or a string?
Yes. RFC 8259 defines a JSON text as any serialized value, so 42 or "hello" on its own is valid. Older specifications required an object or an array at the top level.
Is the order of keys in a JSON object preserved?
The spec says an object is an unordered collection, so you shouldn't rely on key order. Arrays are ordered.
What is the MIME type for JSON?
application/json, and JSON sent between systems should be encoded as UTF-8 without a byte order mark.