| | |

JSON 02 ๐Ÿ“„ JSON Syntax Rules, Data Types, and Structure

โฑ๏ธ Estimated read: 12 min | |

JSON’s syntax is deliberately small. The specification at json.org describes the entire language in a few paragraphs, and the RFC 8259 adds only the encoding details and the interoperability warnings. The smallness is the point: a parser can be written in a few hundred lines, and every language has one in its standard library. The grammar rests on two universal structuresโ€”the collection of name/value pairs and the ordered list of valuesโ€”and the six value types that fill them. The rules are strict about the punctuation and the quoting, and the strictness is what makes the format interoperable across the languages and the platforms .

The data types are where the subtlety lives. JSON has no integer type, no date type, and no binary type. The number is a signed decimal that may have a fraction and may use the exponent notation, and the specification makes no distinction between the integer and the floating-point . The string is a sequence of Unicode characters, and the escape sequences are the mechanism for the characters that cannot appear literally. The object is an unordered set of name/value pairs, and the array is an ordered collection. The null is the empty value, and the booleans are the literal true and false. The types are few, and the constraints on how they combine are the grammar.

Key point: JSON has six value typesโ€”string, number, boolean, null, object, and arrayโ€”and the grammar is defined by the punctuation and the quoting rules. The number is a decimal with no integer/float distinction, and the interoperability limits are the implementation’s responsibility. The strings are Unicode, the objects are unordered name/value collections, and the arrays are ordered lists.


Why the syntax rules are strict

The parsing simplicity problem. The grammar is designed so that a parser can decide what comes next by looking at a single character. The { begins an object, the [ begins an array, the " begins a string, the t/f/n begin the literals, and the digit or the minus sign begins a number . The punctuation is unambiguous, and the parser does not need to look ahead. The simplicity is the reason the parsers are small and the format is fast to parse.

The interoperability problem. The RFC 8259 allows the implementations to set limits on the size of the texts, the depth of the nesting, the range and precision of the numbers, and the length and character contents of the strings . The limits are the implementation’s choice, but the interoperability suffers when two implementations choose different limits. The large integers are the classic case: the RFC notes that the integers in the range [-(2**53)+1, (2**53)-1] are interoperable, and the values outside that range may be approximated . The strictness of the grammar does not solve the interoperability problem, and the RFC is explicit about it.

The duplicate-key problem. The JSON grammar allows an object to contain the same name more than once. The RFC does not require the parsers to reject the duplicates, and the behavior is undefined: the parser may use the first value, the last value, or throw an error . The duplicate keys are a syntax that the grammar permits and the semantics do not define. The strictness is the grammar, not the semantics.

The string escape problem. The string is a sequence of Unicode characters, and the escape sequences are the mechanism for the characters that cannot appear literally. The \" is the double quote, the \\ is the backslash, the \/ is the solidus, the \b/\f/\n/\r/\t are the control characters, and the \uXXXX is the Unicode code point. The RFC notes that the unpaired surrogatesโ€”such as "\uDEAD"โ€”are allowed by the grammar, but the behavior is unpredictable, and the implementations may return different values or throw the runtime exceptions . The escape sequences are the syntax, and the Unicode handling is the interoperability hazard.


a. The six value types and the object structure

The value is the core of the grammar. A value is a string in the double quotes, a number, true, false, null, an object, or an array . The six types are the complete set, and the object and the array are the recursive types that allow the nesting.

{
  "name": "Ada",
  "age": 36,
  "active": true,
  "address": null,
  "tags": ["math", "code"],
  "nested": { "city": "London" }
}

The object begins with the { and ends with the }. Each name is a string followed by the :, and the name/value pairs are separated by the , . The names must be the double-quoted strings, and the duplicate names are allowed by the grammar but undefined in the semantics. The object is the unordered collection, and the order of the names is not significant.

// The object structure
{
  "key1": "value1",
  "key2": "value2"
}

// The array structure
["value1", "value2", "value3"]

The array begins with the [ and ends with the ], and the values are separated by the ,. The array is the ordered collection, and the order is significant . The array can contain the values of any type, including the other arrays and the objects, which is the nesting mechanism.

The string is the sequence of the Unicode characters wrapped in the double quotes. The escape sequences are the backslash-prefixed forms, and the \uXXXX is the four-hex-digit Unicode code point . The string cannot contain the unescaped control characters (the U+0000 to U+001F), and the double quote and the backslash must be escaped.

The number is the signed decimal that may have the fraction and the exponent. The grammar is -?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)? . The leading zeros are not allowed, the octal and the hexadecimal formats are not used, and the NaN and the Infinity are not valid JSON values. The number has no integer/float distinction, and the implementation decides whether to parse it as an integer or a float .


b. The syntax rules and the whitespace

The syntax rules are the punctuation and the quoting. The whitespace can be inserted between any pair of tokens, and the whitespace is not significant . The spaces, the tabs, the newlines, and the carriage returns are the whitespace characters, and the parser ignores them. The whitespace is for the human readability, not for the semantics.

// The whitespace is insignificant
{"name":"Ada","age":36}

// The same JSON with the whitespace
{
  "name": "Ada",
  "age": 36
}

The comments are not allowed. The // and the /* */ are not part of the grammar, and a JSON text that contains them is not valid JSON . The comments are the feature that the JSON5 and the JSONC add, and the strict JSON parsers reject them.

The encoding is the UTF-8 for the exchanged JSON text. The RFC states that the JSON text exchanged between the systems that are not part of a closed ecosystem must be encoded in the UTF-8, and the implementations must not add the byte order mark to the beginning . The UTF-8 is the only encoding that achieves the interoperability, and the other encodings are the legacy.

The top-level value can be any of the six types. The RFC 8259 allows a JSON text to be any value, not just an object or an array, which is the change from the earlier RFC 4627 that required the top-level object or array . The "Hello world!" and the 42 are valid JSON texts.


Complete Example Session

// ============================================
// PART 1: THE OBJECT
// ============================================

const object = {
  "name": "Ada",
  "age": 36,
  "active": true,
  "address": null
};

// The object begins with { and ends with }.
// The names are the double-quoted strings.
// The name/value pairs are separated by the comma.

// ============================================
// PART 2: THE ARRAY
// ============================================

const array = ["math", "code", 42, true, null];

// The array begins with [ and ends with ].
// The values are separated by the comma.
// The order is significant.

// ============================================
// PART 3: THE NESTING
// ============================================

const nested = {
  "user": {
    "name": "Ada",
    "roles": ["admin", "editor"]
  }
};

// The object can contain the object.
// The array can contain the object.
// The nesting is the recursive structure.

// ============================================
// PART 4: THE STRING ESCAPES
// ============================================

const escaped = "The quote is \" and the backslash is \\";

// The \" is the double quote.
// The \\ is the backslash.
// The \n is the newline.
// The \u0041 is the 'A'.

// ============================================
// PART 5: THE NUMBER GRAMMAR
// ============================================

// Valid: 42, -1, 3.14, 1e10, 1.5e-3
// Invalid: 01 (leading zero), 0x1F (hex), NaN, Infinity

// ============================================
// PART 6: THE DUPLICATE KEYS
// ============================================

// The grammar allows the duplicate keys.
// The behavior is undefined: the parser may use the first, the last, or throw.
const duplicate = '{"a": 1, "a": 2}';
JSON.parse(duplicate); // { a: 2 } in JavaScript

// ============================================
// PART 7: THE UNPAIRED SURROGATE
// ============================================

// The grammar allows the unpaired surrogate.
// The behavior is unpredictable.
const surrogate = '{"name": "\\uDEAD"}';
JSON.parse(surrogate); // The length and the value are implementation-dependent

// ============================================
// PART 8: THE TOP-LEVEL VALUE
// ============================================

// The RFC 8259 allows any value at the top level.
JSON.parse('"Hello world!"'); // 'Hello world!'
JSON.parse('42'); // 42
JSON.parse('true'); // true

// ============================================
// PART 9: THE WHITESPACE
// ============================================

// The whitespace is insignificant.
// The two texts are equivalent.
const a = '{"name":"Ada"}';
const b = '{\n  "name": "Ada"\n}';
JSON.parse(a); // { name: 'Ada' }
JSON.parse(b); // { name: 'Ada' }

// ============================================
// PART 10: THE CHECKLIST
// ============================================

// [ ] The six value types are understood.
// [ ] The object is the unordered name/value collection.
// [ ] The array is the ordered value list.
// [ ] The string escapes are understood.
// [ ] The number grammar is understood.
// [ ] The duplicate keys are avoided.
// [ ] The unpaired surrogates are avoided.
// [ ] The top-level value can be any type.
// [ ] The whitespace is insignificant.

The ten parts covered the object, the array, the nesting, the string escapes, the number grammar, the duplicate keys, the unpaired surrogate, the top-level value, the whitespace, and the checklist. The through-line is that the grammar is small, and the semantics have the edges.


Quick Reference

The six value types

TypeSyntaxExample
StringThe double quotes"text"
NumberThe decimal42, 3.14, 1e10
BooleanThe literaltrue, false
NullThe literalnull
ObjectThe {} braces{"key": "value"}
ArrayThe [] brackets["a", "b"]

The string escapes

EscapeCharacter
\"The double quote
\\The backslash
\/The solidus
\bThe backspace
\fThe form feed
\nThe newline
\rThe carriage return
\tThe tab
\uXXXXThe Unicode code point

The number grammar

ValidInvalid
4201 (the leading zero)
-10x1F (the hex)
3.14NaN
1e10Infinity
1.5e-3.5 (the missing integer part)

The object and the array

AspectObjectArray
Delimiter{}[]
OrderUnorderedOrdered
KeysThe stringsThe indices
DuplicatesAllowed but undefinedAllowed

Best Practices

โœ… Do This:

// Use the double quotes for the strings and the names
{ "name": "Ada" }                                              // โœ…

// Use the valid number grammar
{ "age": 36, "score": 3.14 }                                   // โœ…

// Avoid the duplicate keys
{ "a": 1, "b": 2 }                                             // โœ…

โŒ Don’t Do This:

// Use the single quotes
{ 'name': 'Ada' }                                              // โŒ

// Use the trailing comma
{ "name": "Ada", }                                             // โŒ

// Use the comments
{ "name": "Ada" } // the comment                                // โŒ

Common Pitfalls

PitfallWhy It HappensFix
The parse failsThe single quote or the trailing commaUse the double quotes and remove the comma
The number is roundedThe integer is larger than 2^53Serialize as a string
The duplicate key winsThe parser uses the last valueAvoid the duplicates
The surrogate is invalidThe unpaired surrogateUse the valid Unicode
The comment is rejectedThe comments are not in the grammarRemove the comments

Real-World Examples

1. The object

{ "name": "Ada", "age": 36 }

2. The array

["math", "code", "physics"]

3. The nested object

{ "user": { "name": "Ada" } }

4. The string escape

{ "quote": "He said \"hello\"" }

5. The unicode escape

{ "letter": "\u0041" }

6. The number

{ "pi": 3.14159, "big": 1e10 }

7. The boolean and null

{ "active": true, "address": null }

8. The top-level string

"Hello world!"

9. The top-level number

42

10. The whitespace

{ "name": "Ada" }

Visual

The Six Value Types

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE SIX VALUE TYPES                                         โ”‚
โ”‚                                                              โ”‚
โ”‚  Primitive:                                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”‚
โ”‚  โ”‚ string      โ”‚  โ”‚ number      โ”‚  โ”‚ boolean     โ”‚         โ”‚
โ”‚  โ”‚ "text"      โ”‚  โ”‚ 42, 3.14    โ”‚  โ”‚ true/false  โ”‚         โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                            โ”‚
โ”‚  โ”‚ null        โ”‚                                            โ”‚
โ”‚  โ”‚ null        โ”‚                                            โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                            โ”‚
โ”‚                                                              โ”‚
โ”‚  Structured:                                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                          โ”‚
โ”‚  โ”‚ object      โ”‚  โ”‚ array       โ”‚                          โ”‚
โ”‚  โ”‚ {"key":val} โ”‚  โ”‚ [val, val]  โ”‚                          โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Object Structure

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE OBJECT                                                  โ”‚
โ”‚                                                              โ”‚
โ”‚  {                                                           โ”‚
โ”‚    "name": "Ada",    โ† the name/value pair                  โ”‚
โ”‚    "age": 36,        โ† the comma separator                  โ”‚
โ”‚    "active": true    โ† the last pair (no comma)             โ”‚
โ”‚  }                                                           โ”‚
โ”‚                                                              โ”‚
โ”‚  The name is the double-quoted string.                      โ”‚
โ”‚  The colon separates the name and the value.                โ”‚
โ”‚  The comma separates the pairs.                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The String Escapes

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE ESCAPE SEQUENCES                                        โ”‚
โ”‚                                                              โ”‚
โ”‚  \"  โ†’  the double quote                                    โ”‚
โ”‚  \\  โ†’  the backslash                                       โ”‚
โ”‚  \n  โ†’  the newline                                         โ”‚
โ”‚  \t  โ†’  the tab                                             โ”‚
โ”‚  \u0041  โ†’  the 'A' (the Unicode code point)                โ”‚
โ”‚                                                              โ”‚
โ”‚  The unescaped control characters are not allowed.          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Value typesString, number, boolean, null, object, array
ObjectThe unordered name/value collection with the {}
ArrayThe ordered value list with the []
StringThe double-quoted Unicode sequence with the escapes
NumberThe signed decimal with the fraction and the exponent
WhitespaceInsignificant, allowed between the tokens
CommentsNot allowed
Top-level valueAny of the six types

Key takeaways:

  • JSON has six value types and two structures. The value is a string, a number, a boolean, null, an object, or an array. The object is the unordered name/value collection, and the array is the ordered value list .
  • The number has no integer/float distinction. The grammar is a signed decimal with the optional fraction and exponent, and the implementation decides how to parse it. The integers outside the range [-(2^53)+1, (2^53)-1] are not interoperable .
  • The string escapes are the mechanism for the special characters. The \", \\, \n, and \uXXXX are the common escapes, and the unescaped control characters are not allowed .
  • The duplicate keys are allowed by the grammar but undefined in the semantics. The parser may use the first value, the last value, or throw an error, and the behavior is not specified .
  • The unpaired surrogates are allowed by the grammar but unpredictable in the behavior. The "\uDEAD" is a valid JSON string according to the ABNF, but the implementations may return different values or throw the runtime exceptions .

Remember: JSON’s syntax is small and strict. The six value types, the object and the array structures, and the punctuation rules are the entire grammar. The number is a decimal with no integer distinction, the string is a Unicode sequence with the escapes, and the object is the unordered collection. The duplicate keys and the unpaired surrogates are the grammar’s edges, and the behavior is undefined. The strictness is the interoperability, and the edges are the hazards.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!