JSON Grammar Rules
Changelog
| Date | Change Description |
|---|---|
| May 11, 2026 | Added notes about JSON grammar rules using McKeeman Form |
JSON Grammer Rules in McKeeman Form
The following is the JSON grammar defined in the McKeeman Form1
json
element
value
object
array
string
number
true
false
null
object
'{' ws '}'
'{' members '}'
members
member
member ',' members
member
ws string ws ':' element
array
'[' ws ']'
'[' elements ']'
elements
element
element ',' elements
element
ws value ws
string
'"' characters '"'
characters
""
character characters
character
'0020' . '10FFFF' - '"' - '\'
'\' escape
escape
'"'
'\'
'/'
'b'
'f'
'n'
'r'
't'
'u' hex hex hex hex
hex
digit
'A' . 'F'
'a' . 'f'
number
integer fraction exponent
integer
digit
onenine digits
'-' digit
'-' onenine digits
digits
digit
digit digits
digit
'0'
onenine
onenine
'1' . '9'
fraction
""
'.' digits
exponent
""
'E' sign digits
'e' sign digits
sign
""
'+'
'-'
ws
""
'0020' ws
'000A' ws
'000D' ws
'0009' ws
Understanding the Parsing Order (Top-Down Approach)
Step 1: Start with JSON
Rule:
Meaning: A JSON document is exactly ONE element. Example:
{"name": "Alice"} ← This is ONE element (an object)
[1, 2, 3] ← This is ONE element (an array)
"hello" ← This is ONE element (a string)
42 ← This is ONE element (a number)
true ← This is ONE element (a literal)
You cannot have:
Step 2: Parse an Element (Allow Whitespace Around It)
Rule:
Meaning: An element is: [optional whitespace] + [a value] + [optional whitespace]
Whitespace can be Spaces, Newlines, Tabs, Carriage returns, or nothing at all
Examples:
{"name":"Alice"} ← No whitespace
{ "name" : "Alice" } ← Whitespace around everything
{
"name": "Alice"
} ← Newlines and indentation (also whitespace)
42 ← Whitespace before and after
All of these are valid because whitespace is stripped away in the grammar rules.
Step 3: Determine What Type of Value You Have
Rule:
Meaning: A value can be ONE of these six things:
- object — starts with
{ - array — starts with
[ - string — starts with
" - number — starts with a digit, minus sign, or decimal
- true — the literal word true
- false — the literal word false
- null — the literal word null
Examples:
{} ← Value is an object
[] ← Value is an array
"hello" ← Value is a string
42 ← Value is a number
3.14 ← Value is a number
-5 ← Value is a number
true ← Value is the literal true
false ← Value is the literal false
null ← Value is the literal null
Decision Tree:
- Does it start with
{? → Follow the OBJECT rules (Step 4) - Does it start with
[? → Follow the ARRAY rules (Step 5) - Does it start with
"? → Follow the STRING rules (Step 7) - Is it a number? → Follow the NUMBER rules (Step 8)
- Is it true, false, or null? → Done! It's a literal
BRANCH A: OBJECTS
Step 4: Parse an Object
Rules:
Meaning: An object is either:
- An opening brace
{,optional whitespace, and a closing brace}— Empty Object - An opening brace
{, one or more members, and a closing brace}— Object with Data
Examples:
{} ← Empty object
{ "name": "Alice" } ← Object with 1 member
{ "name": "Alice", "age": 30 } ← Object with 2 members
{
"name": "Alice",
"age": 30,
"city": "NYC"
} ← Object with 3 members (formatted)
If the object is NOT empty, follow to Step 6 for members.
Step 6: Parse Members (Key-Value Pairs)
Rules:
Meaning: Members are either:
- A single member
- A member, then a comma, then more members (recursive)
This means:
One member: "name": "Alice"
Two members: "name": "Alice", "age": 30
Many members: chain them with commas
Each member is:
Meaning:
- Optional whitespace (ws)
- A string (the key name)
- Optional whitespace (ws)
- A colon :
- An element (the value)
Examples:
"name": "Alice"
↓
ws + string "name" + ws + ':' + element "Alice"
"age": 30
↓
ws + string "age" + ws + ':' + element 30
"hobbies": ["reading", "coding"]
↓
ws + string "hobbies" + ws + ':' + element [array]
For the string part, follow Step 7. For the element part, recursively follow Step 2 (which leads back to Step 3).
BRANCH B: ARRAYS
Step 5: Parse an Array
Rules:
Meaning: An array is either:
- An opening bracket
[,optional whitespace, and a closing bracket]— Empty Array - An opening bracket
[, one or more elements, and a closing bracket]— Array with Data
Examples:
[] ← Empty array
[ 1, 2, 3 ] ← Array with 3 numbers
[ "a", "b", "c" ] ← Array with 3 strings
[ 1, "hello", true ] ← Array with mixed types
[
{ "name": "Alice" },
{ "name": "Bob" }
] ← Array with 2 objects (formatted)
If the array is NOT empty, follow to the next rule for elements.
Elements Rule:
Meaning: Elements are either:
- A single element
- An element, then a comma, then more elements (recursive)
Examples:
For each element, recursively follow Step 2 (which leads back to Step 3).
BRANCH C: STRINGS
Step 7: Parse a String
Rule:
Meaning: A string is:
- An opening double quote
" - Zero or more characters (the content)
- A closing double quote
"
Characters Rule:
Meaning: Characters can be:
- Empty (empty string is allowed)
- A single character followed by more characters (recursive)
Examples:
"" ← Empty string (zero characters)
"hello" ← String with 5 characters: h, e, l, l, o
"Alice" ← String with 5 characters: A, l, i, c, e
"Hello, World!" ← String with 13 characters including space, comma, punctuation
Character Rule:
Meaning: A character can be:
- Any Unicode character from
U+0020(space) toU+10FFFF(max Unicode) - EXCEPT the double quote
"(because that ends the string) - EXCEPT the backslash
\(because that starts escape sequences) - OR a backslash
\followed by an escape sequence
Escape Sequences Rule:
Meaning: After a backslash, you can use:
\"— A literal double quote character\\— A literal backslash character\/— A literal forward slash (optional escaping)\b— Backspace character\f— Form feed character\n— Newline character\r— Carriage return character\t— Tab character\ufollowed by 4 hex digits — Unicode character by code point
Examples:
"Hello" ← Plain text (no escapes)
"Hello \"World\"" ← Contains: Hello "World"
(quotes must be escaped)
"Path: C:\\Users" ← Contains: Path: C:\Users
(backslash must be escaped)
"Line1\nLine2" ← Contains a newline in the middle
Renders as:
Line1
Line2
"Copyright \u00A9" ← \u00A9 is Unicode for ©
Renders as: Copyright ©
"Quote: \"Hi\"" ← Contains: Quote: "Hi"
BRANCH D: NUMBERS
Step 8: Parse a Number
Rule:
Meaning: A number has three optional parts (all can be omitted or present):
- integer — required (at least the digits part)
- fraction — optional (decimal part)
- exponent — optional (scientific notation)
Part 1: Integer (Mandatory)
Rules:
Meaning: An integer is either:
- A single digit (0-9)
- A number from 1-9, followed by zero or more digits, optionally preceded by a minus sign
- OR a minus sign, followed by a digit, OR a minus sign followed by 1-9 and more digits
Key point: No Leading Zeros (except for 0 itself)
Examples:
0 ← Single digit
5 ← Single digit
42 ← Two digits (no leading zero)
-1 ← Negative single digit
-42 ← Negative number
Invalid Examples:
Part 2: Fraction (Optional)
Rule:
Meaning: Fraction can be:
- Empty (nothing)
- A decimal point . followed by one or more digits
Examples:
Invalid Examples:
Part 3: Exponent (Optional)
Rule:
Meaning: Exponent can be:
- Empty (nothing)
- An uppercase
E, optional sign, and digits - A lowercase
e, optional sign, and digits
Sign Rule:
Meaning: Sign can be empty, a plus +, or a minus -.
Examples:
42 ← No exponent
42E10 ← Exponent: E10 (42 × 10^10)
42e-5 ← Exponent: e-5 (42 × 10^-5)
1.5E+3 ← Exponent: E+3 (1.5 × 10^3)
3.14e0 ← Exponent: e0 (3.14 × 10^0)
Step 9: Whitespace Rules (ws)
Rule:
Meaning: Whitespace (ws) can be:
- Empty (nothing)
- A space character (
U+0020) followed by more whitespace - A newline character (
U+000A) followed by more whitespace - A carriage return character (
U+000D) followed by more whitespace - A tab character (
U+0009) followed by more whitespace
This is recursive, meaning you can have any combination of these.
Examples:
(no space) ← Empty ws
(single space)
(two spaces)
(tab)
(newline)
(carriage return)
(4 spaces) ← Indentation
(spaces and tabs mixed)
Where whitespace appears in JSON:
{ "name" : "Alice" }
↓
{} = braces must be together
ws = space before "name"
ws = space after "name"
ws = space before :
ws = space after :
ws = space after "Alice"
ws = space before }
[1, 2, 3]
↓
[] = brackets must be together
ws = after [
ws = after 1
ws = after ,
ws = after 2
ws = after ,
ws = after 3
ws = before ]
Flowchart Summary of Parsing JSON
flowchart TD
A["STEP 1: json<br/>Must contain ONE element"] --> B["STEP 2: element<br/>Strip whitespace"]
B --> C{"STEP 3: value<br/>What type?"}
C -->|starts with brace| D["STEP 4: object<br/>Parse braces"]
C -->|starts with bracket| E["STEP 5: array<br/>Parse brackets"]
C -->|starts with quote| F["STEP 7: string<br/>Parse quoted text"]
C -->|numeric or minus| G["STEP 8: number<br/>integer.fraction e-exp"]
C -->|true/false/null| H["Literal value<br/>DONE"]
D --> D1{"Object<br/>empty?"}
D1 -->|yes| D2["DONE: empty object {}"]
D1 -->|no: has members| D3["STEP 6: members<br/>Parse key:value pairs"]
D3 --> D4["STEP 6a: member<br/>string : element"]
D4 --> D5["STEP 7: string<br/>Parse key"]
D5 --> D6["Parse colon"]
D6 --> D7["STEP 2 recursive<br/>Parse value"]
D7 --> D9{"More<br/>members?"}
D9 -->|yes, comma| D10["Parse comma"]
D10 --> D3
D9 -->|no| D2
E --> E1{"Array<br/>empty?"}
E1 -->|yes| E2["DONE: empty array []"]
E1 -->|no: has elements| E3["STEP 5b: elements<br/>Parse values"]
E3 --> E4["STEP 2 recursive<br/>Parse element"]
E4 --> E6{"More<br/>elements?"}
E6 -->|yes, comma| E7["Parse comma"]
E7 --> E3
E6 -->|no| E2
F --> F1["STEP 7a: characters<br/>Read until closing quote"]
F1 --> F2{"Has<br/>backslash?"}
F2 -->|no| F3["Regular character"]
F2 -->|yes| F4["STEP 7b: escape<br/>Handle special chars"]
F3 --> F5{"More chars?"}
F4 --> F5
F5 -->|yes| F1
F5 -->|no| F6["DONE: string"]
G --> G1["STEP 8a: integer<br/>Digits, no leading zeros"]
G1 --> G2{"Decimal<br/>point?"}
G2 -->|yes| G3["STEP 8b: fraction<br/>dot and digits"]
G2 -->|no| G4{"Exponent<br/>E or e?"}
G3 --> G5{"Exponent<br/>E or e?"}
G4 -->|yes| G6["STEP 8c: exponent<br/>E/e with sign and digits"]
G5 -->|yes| G6
G4 -->|no| G7["DONE: number"]
G5 -->|no| G7
G6 --> G7
H --> H2["DONE: literal"]
style A fill:#6366f1,stroke:#4f46e5,color:#fff,stroke-width:3px
style B fill:#06b6d4,stroke:#0891b2,color:#fff,stroke-width:2px
style C fill:#f59e0b,stroke:#d97706,color:#000,stroke-width:2px
style D fill:#8b5cf6,stroke:#7c3aed,color:#fff,stroke-width:2px
style E fill:#10b981,stroke:#059669,color:#fff,stroke-width:2px
style F fill:#f97316,stroke:#ea580c,color:#fff,stroke-width:2px
style G fill:#ef4444,stroke:#dc2626,color:#fff,stroke-width:2px
style H fill:#ec4899,stroke:#be185d,color:#fff,stroke-width:2px
style D2 fill:#8b5cf6,stroke:#7c3aed,color:#fff
style E2 fill:#10b981,stroke:#059669,color:#fff
style F6 fill:#f97316,stroke:#ea580c,color:#fff
style G7 fill:#ef4444,stroke:#dc2626,color:#fff
style H2 fill:#ec4899,stroke:#be185d,color:#fff
-
D. Crockford, “McKeeman Form,” Crockford.com, Jan. 9, 2020. [Online]. Available: https://www.crockford.com/mckeeman.html. [Accessed: 11-May-2026]. ↩