Formal Grammar
The complete formal grammar specification for JSON5 implementers and language enthusiasts.
TL;DR: This page contains the formal grammar specification for JSON5 in ABNF notation. It's primarily intended for implementers building JSON5 parsers or tools.
Grammar Notation
This specification uses a modified ABNF (Augmented Backus-Naur Form) notation similar to that used in ECMAScript specifications.
Notation Conventions
| Notation | Meaning | Example |
|---|---|---|
A B | A followed by B (concatenation) | { } means { then } |
A | B | A or B (alternation) | true | false |
A? | Zero or one A (optional) | Sign? optional sign |
A* | Zero or more A | Digit* any digits |
A+ | One or more A | Digit+ at least one digit |
"text" | Literal text | "null" the word null |
[a-z] | Character range | [0-9] digits 0-9 |
<NAME> | Unicode category or named character | <TAB> tab character |
JSON5 Values
A JSON5 document consists of a single JSON5 value optionally surrounded by whitespace and comments.
Value Productions
JSON5Text : JSON5Value JSON5Value : JSON5Null JSON5Boolean JSON5String JSON5Number JSON5Object JSON5Array JSON5Null : "null" JSON5Boolean : "true" "false"Note: Unlike JSON, which only allows objects or arrays at the top level, JSON5 allows any value type as the root element.
Object Grammar
Objects are unordered collections of key-value pairs enclosed in curly braces.
Object Productions
JSON5Object : "{" "}" "{" JSON5MemberList "}" "{" JSON5MemberList "," "}" JSON5MemberList : JSON5Member JSON5MemberList "," JSON5Member JSON5Member : JSON5MemberName ":" JSON5Value JSON5MemberName : JSON5Identifier JSON5StringIdentifier Grammar
JSON5Identifier : IdentifierName IdentifierName : IdentifierStart IdentifierName IdentifierPart IdentifierStart : UnicodeLetter "$" "_" "\" UnicodeEscapeSequence IdentifierPart : IdentifierStart UnicodeCombiningMark UnicodeDigit UnicodeConnectorPunctuation <ZWNJ> <ZWJ> UnicodeLetter : any character in Unicode categories "Lu" "Ll" "Lt" "Lm" "Lo" "Nl" UnicodeDigit : any character in Unicode category "Nd" UnicodeCombiningMark : any character in Unicode categories "Mn" "Mc" UnicodeConnectorPunctuation : any character in Unicode category "Pc"Array Grammar
Arrays are ordered sequences of values enclosed in square brackets.
Array Productions
JSON5Array : "[" "]" "[" JSON5ElementList "]" "[" JSON5ElementList "," "]" JSON5ElementList : JSON5Value JSON5ElementList "," JSON5ValueString Grammar
Strings can use single or double quotes and support various escape sequences.
String Productions
JSON5String : '"' JSON5DoubleStringCharacter? '"' "'" JSON5SingleStringCharacter? "'" JSON5DoubleStringCharacter : JSON5DoubleStringCharacter JSON5DoubleStringCharacter? JSON5SingleStringCharacter : JSON5SingleStringCharacter JSON5SingleStringCharacter? JSON5DoubleStringCharacter : SourceCharacter but not '"' or "\" or LineTerminator "\" EscapeSequence LineContinuation <LS> <PS> JSON5SingleStringCharacter : SourceCharacter but not "'" or "\" or LineTerminator "\" EscapeSequence LineContinuation <LS> <PS> LineContinuation : "\" LineTerminatorSequenceEscape Sequences
EscapeSequence : CharacterEscapeSequence "0" [lookahead not in DecimalDigit] HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence : SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter : "'" | '"' | "\" | "b" | "f" | "n" | "r" | "t" | "v" NonEscapeCharacter : SourceCharacter but not EscapeCharacter or LineTerminator EscapeCharacter : SingleEscapeCharacter DecimalDigit "x" "u" HexEscapeSequence : "x" HexDigit HexDigit UnicodeEscapeSequence : "u" HexDigit HexDigit HexDigit HexDigit HexDigit : [0-9a-fA-F]Number Grammar
Numbers can be decimal or hexadecimal, and include special values like Infinity and NaN.
Number Productions
JSON5Number : JSON5NumericLiteral "Infinity" "NaN" JSON5NumericLiteral : NumericLiteral "+" NumericLiteral "-" NumericLiteral NumericLiteral : DecimalLiteral HexIntegerLiteral DecimalLiteral : DecimalIntegerLiteral "." DecimalDigits? ExponentPart? "." DecimalDigits ExponentPart? DecimalIntegerLiteral ExponentPart? DecimalIntegerLiteral : "0" NonZeroDigit DecimalDigits? DecimalDigits : DecimalDigit DecimalDigits DecimalDigit DecimalDigit : [0-9] NonZeroDigit : [1-9] ExponentPart : ExponentIndicator SignedInteger ExponentIndicator : "e" | "E" SignedInteger : DecimalDigits "+" DecimalDigits "-" DecimalDigits HexIntegerLiteral : "0x" HexDigit+ "0X" HexDigit+ Note: Unlike JSON, JSON5 allows leading decimal points (.5), trailing decimal points (5.), explicit positive signs (+5), and hexadecimal literals (0xFF).
Lexical Grammar
Whitespace, line terminators, and comments that separate tokens.
Whitespace
WhiteSpace : <TAB> U+0009 Tab <VT> U+000B Vertical Tab <FF> U+000C Form Feed <SP> U+0020 Space <NBSP> U+00A0 No-Break Space <BOM> U+FEFF Byte Order Mark <USP> Any Unicode "Zs" category characterLine Terminators
LineTerminator : <LF> U+000A Line Feed <CR> U+000D Carriage Return <LS> U+2028 Line Separator <PS> U+2029 Paragraph Separator LineTerminatorSequence : <LF> <CR> [lookahead not in <LF>] <LS> <PS> <CR> <LF>Comments
Comment : MultiLineComment SingleLineComment MultiLineComment : "/*" MultiLineCommentChars? "*/" MultiLineCommentChars : MultiLineNotAsteriskChar MultiLineCommentChars? "*" PostAsteriskCommentChars? PostAsteriskCommentChars : MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentChars? "*" PostAsteriskCommentChars? MultiLineNotAsteriskChar : SourceCharacter but not "*" MultiLineNotForwardSlashOrAsteriskChar : SourceCharacter but not "/" or "*" SingleLineComment : "//" SingleLineCommentChars? SingleLineCommentChars : SingleLineCommentChar SingleLineCommentChars? SingleLineCommentChar : SourceCharacter but not LineTerminatorReserved Words as Keys
Reserved words are valid unquoted object keys in JSON5. The JSON5Identifier production above is IdentifierName with no exclusion, and ECMAScript 5.1 defines IdentifierName to include every reserved word. So { class: 'container' } and { null: 1 } parse, and both the JavaScript and the Python reference implementations accept them.
These are the words ECMAScript 5.1 reserves for its own grammar. JSON5 permits all of them as unquoted keys:
ReservedWord : Keyword FutureReservedWord NullLiteral BooleanLiteral Keyword : "break" "case" "catch" "continue" "debugger" "default" "delete" "do" "else" "finally" "for" "function" "if" "in" "instanceof" "new" "return" "switch" "this" "throw" "try" "typeof" "var" "void" "while" "with" FutureReservedWord : "class" "const" "enum" "export" "extends" "import" "super" FutureReservedWord (strict mode) : "implements" "interface" "let" "package" "private" "protected" "public" "static" "yield" NullLiteral : "null" BooleanLiteral : "true" "false" Style note: Quoting a reserved word is optional, not required - { class: 'value' }, { "class": "value" } and { 'class': 'value' } all parse to the same object. Quote it when you want the key to read unambiguously to someone skimming the file. What genuinely cannot be unquoted is a key that is not an IdentifierName at all: { 'my-key': 1 }, { '123abc': 1 } and { 'has spaces': 1 } must be quoted.
Building a JSON5 Parser?
Check out the reference implementation or explore language-specific libraries.