QCON is a JSON superset designed to fill in the gaps of base JSON and round out its features to better cover common serialization needs for low level programming.
# Check out this comment
[
inf, # Direct representation for +/- infinity
nan, # Direct represenation for NaN
[ 1, 1.0 ], # Integer and floating-point are distinct types
0x1A, # Hex
0x17, # Octal
0b10, # Binary
"\x12", # Two digit unicode codepoint
"\u1234", # Four digit unicode codepoint
"\U12345678", # Eight digit unicode codepoint
D1970-01-01, # Date
T12:34:56.789, # Time
D1970-01-01T00:00:00Z, # Datetime
null, # Trailing comma allowed
]
See grammar.md for a complete description of the QCON syntax.
Compared to JSON
QCON is a strict superset of JSON, meaning that every valid JSON document is a valid QCON document.
- Adds
# Comments - Adds date, time, and datetime types
- Separates the "number" type into two distinct "integer" and "floater" types, distinguished by the presence of a
decimal point
.or exponente - Adds
inf,+inf, and-infto represent floating-point infinity values - Adds
nanto represent a floating-point NaN value - Adds support for hex, octal, and binary integers with the
0x,0o, and0bprefixes, respectively - Allows numbers to begin with
+ - Allows numbers to have leading zeroes
- Allows the last element in an object or array to have one trailing comma
- Adds
\xand\Uunicode escape prefixes to support 2 and 8 digit codepoint representations, respectively. This is in addition to the 4 digit\uprefix available in JSON - Allows for
"adjacent" "string" "concatenation". This is especially useful for splitting long strings accross multiple lines - Adds the
\aand\vescape characters
Compared to JSON5
JSON5 is great, but there are a few things I don't like that motivated the creation of QCON. Most notably, it lacks a datetime type, and some of its features (such as unquoted keys) add considerable parser complexity/cost without providing meaningful benefit, in my opinion.
Some minor differences omitted
- Adds date, time, and datetime types
- Adds octal
0oand binary0bintegers - Uses
infinstead ofInfinityandnaninstead ofNaN - Uses
#for line comments instead of//, and does not support/* block */comments - Does not support unquoted keys
- Does not support single quote strings
- Does not support escaped newlines
- Does not support additional whitespace characters
An object is a key-value collection of elements and is denoted with { braces }.
A QCON object is the same as a JSON object, except that the last element may have one trailing comma.
{
"Empty": {},
"Typical": { "k1": 123, "k2": true, "k3": null },
"Trailing comma": { "key": "val" },
}
An array is a list of values and is denoted with [ brackets ].
A QCON array is the same as a JSON array, except that the last element may have one trailing comma.
[
[], # Empty
[ 123, true, null ], # Typical
[ "val" ], # Trailing commas
]
A string is a sequence of unicode codepoints and is denoted with " double quotes ".
"I'm a string made from Úñïçôðè"
Adjacent strings are combined as one.
"This is a comp" "lete sentence."
{
"Script": "Water. Earth. Fire. Air. Long ago, the four nations lived"
" together in harmony. Then, everything changed when the"
" Fire Nation attacked. Only the Avatar, master of all four"
" elements, could stop them, but when the world needed him"
" most, he vanished."
}
Certain special characters can be escaped.
| Sequence | Character | Name |
|---|---|---|
\" |
" | Double quote |
\\ |
\ | Back slash |
\/ |
/ | Forward slash |
\0 |
U+0000 | Null |
\a |
U+0007 | Bell |
\b |
U+0008 | Backspace |
\t |
U+0009 | Tab |
\n |
U+000A | Newline |
\v |
U+000B | Vertical tab |
\f |
U+000C | Form feed |
\r |
U+000D | Carriage return |
"To be\r\nor not\tto be"
Any codepoint can be directly encoded using the prefix \x, \u, or \U followed by two, four, or eight hex digits
respectively.
"\x12 \u1234 \U12345678"
An integer is a whole number, without decimal point or exponent.
An integer may be prefixed with a sign +/-.
An integer may have leading zeroes.
[ 123, +123, -123, 000123 ]
A hexadecimal, octal, or binary integer may be represented when prefixed with 0x, 0o, or 0b respectively.
{
"hex": 0x0123456789ABCDEF,
"octal": 0o01234567
"binary": 0b01
}
A floater is a number with a decimal point or exponent.
A floater may be prefixed with a sign +/-.
A floater may have leading zeroes.
[ 123.4, +123.4, -123.4, 000123.4, 12.34e2, 12.34e+2, 1234e-2 ]
A whole number floater must end in .0 or contain an exponent to disambiguate it from an integer.
[
7, # Integer
7.0, # Floater
7e0 # Floater
]
Infinity may be represented with inf.
NaN may be represented with nan.
[
inf, # Positive infinity
+inf, # Positive infinity
-inf, # Negative infinity
nan # NaN
]
A boolean may be either true or false.
{
"The cake is a lie": true,
"Take life's lemons": false
}
A date represents a gregorian calendar date in the ISO 8601 format YYYY-MM-DD.
A date is prefixed with D to streamline parsing.
{ "Date of writing": D2023-02-27 }
A time represents a 24-hour time of day in the ISO 8601 format Thh:mm:ss.
T12:05:33 # Five minutes and 33 seconds past lunch time
A time may have any number of subsecond fractional digits.
{
"High precision lunch time": T12:00:00.000000007
}
A datetime combines a date and a time into a specific timepoint.
D2023-02-27T12:05:33.069
A datetime may specify a timezone, either with Z to indicate UTC time, of a ±hh:mm offset.
If no timezone is specified, the datetime is in local time.
{
"Local" : D2023-02-27T12:05:33,
"UTC" : D2023-02-27T19:05:33Z,
"Pacific" : D2023-02-27T12:05:33-07:00
}
A null value may be represented with null.
{ "This statement is false": null }