JSON6 Formal Grammar

The complete formal grammar specification for JSON6 implementers and language enthusiasts.

TL;DR: This page contains the formal grammar specification for JSON6 in ABNF notation. It's primarily intended for implementers building JSON6 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

JSON6 Values

A JSON6 document consists of a single JSON6 value optionally surrounded by whitespace and comments.

Value Productions

JSON6Text : JSON6Value JSON6Value : JSON6Null JSON6Boolean JSON6String JSON6Number JSON6Object JSON6Array JSON6Null : "null" JSON6Boolean : "true" "false"

Note: Unlike JSON, which only allows objects or arrays at the top level, JSON6 allows any value type as the root element.

Object Grammar

Objects are unordered collections of key-value pairs enclosed in curly braces.

Object Productions

JSON6Object : "{" "}" "{" JSON6MemberList "}" "{" JSON6MemberList "," "}" JSON6MemberList : JSON6Member JSON6MemberList "," JSON6Member JSON6Member : JSON6MemberName ":" JSON6Value JSON6MemberName : JSON6Identifier JSON6String

Identifier Grammar

JSON6Identifier : 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

JSON6Array : "[" "]" "[" JSON6ElementList "]" "[" JSON6ElementList "," "]" JSON6ElementList : JSON6Value JSON6ElementList "," JSON6Value

String Grammar

Strings can use single or double quotes and support various escape sequences.

String Productions

JSON6String : '"' JSON6DoubleStringCharacter? '"' "'" JSON6SingleStringCharacter? "'" JSON6DoubleStringCharacter : JSON6DoubleStringCharacter JSON6DoubleStringCharacter? JSON6SingleStringCharacter : JSON6SingleStringCharacter JSON6SingleStringCharacter? JSON6DoubleStringCharacter : SourceCharacter but not '"' or "\" or LineTerminator "\" EscapeSequence LineContinuation <LS> <PS> JSON6SingleStringCharacter : SourceCharacter but not "'" or "\" or LineTerminator "\" EscapeSequence LineContinuation <LS> <PS> LineContinuation : "\" LineTerminatorSequence

Escape 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

JSON6Number : JSON6NumericLiteral "Infinity" "NaN" JSON6NumericLiteral : 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, JSON6 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 character

Line 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 LineTerminator

Reserved Words as Keys

Reserved words are valid unquoted object keys in JSON6. The JSON6Identifier 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. JSON6 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 JSON6 Parser?

Check out the reference implementation or explore language-specific libraries.