=== empty object
{}
---
{}
=== empty array
[]
---
[]
=== null literal
null
---
null
=== boolean true
true
---
true
=== boolean false
false
---
false
=== integer zero
0
---
0
=== integer negative zero
-0
---
-0
=== integer positive
123
---
123
=== integer negative
-456
---
-456
=== integer 2^53-1 (safe JS max)
9007199254740991
---
9007199254740991
=== float simple
3.14
---
3.14
=== float negative
-0.125
---
-0.125
=== float many fraction digits
1.000000000123
---
1.000000000123
=== float with exponent (lowercase)
1e6
---
1e6
=== float with exponent (uppercase, positive sign)
2E+8
---
2E+8
=== float with negative exponent
7e-3
---
7e-3
=== float decimal mantissa with exponent
6.022e23
---
6.022e23
=== empty string
""
---
""
=== simple ascii string
"Hello, world!"
---
"Hello, world!"
=== string with escaped quote
"He said: \"JSON is great.\""
---
"He said: \"JSON is great.\""
=== string with backslash
"Path C:\\\\Program Files\\\\App"
---
"Path C:\\\\Program Files\\\\App"
=== string with solidus
"Use https://maml.dev/"
---
"Use https://maml.dev/"
=== string containing all compact escape sequence
"\n\r\t\\\""
---
"\n\r\t\\\""
=== string with unicode escape
"\u{263A}"
---
"\u263A"
=== string with very short unicode escape
"\u{C}"
---
"\u000C"
=== string with emoji
"\u{1F95D}"
---
"🥝"
=== string with null and unit separators
"\u{0000}\u{001F}"
---
"\u0000\u001F"
=== string with max unicode range
"\u{10FFFF}"
---
"\uDBFF\uDFFF"
=== multilingual string
"Привет 世界 مرحبا"
---
"Привет 世界 مرحبا"
=== simple object one pair
{"a":1}
---
{"a":1}
=== object with multiple types
{"n":null,"t":true,"f":false,"i":42,"d":3.5,"s":"ok"}
---
{"n":null,"t":true,"f":false,"i":42,"d":3.5,"s":"ok"}
=== nested object
{"outer":{"inner":{"key":"value"}}}
---
{"outer":{"inner":{"key":"value"}}}
=== object with empty key
{"": "empty-key"}
---
{"": "empty-key"}
=== object with special character keys
{"a-b":1,"a b":2,"a:b":3,"a,b":4}
---
{"a-b":1,"a b":2,"a:b":3,"a,b":4}
=== object with escaped newline in key
{"a\nb":"c"}
---
{"a\nb":"c"}
=== array single element
[1]
---
[1]
=== array of integers
[0,1,2,3,4,5,6,7,8,9]
---
[0,1,2,3,4,5,6,7,8,9]
=== array of booleans
[true,false,true,false]
---
[true,false,true,false]
=== array of nulls
[null,null,null]
---
[null,null,null]
=== array mixed types
[null,true,42,3.14,"x",{"a":1},[2,3]]
---
[null,true,42,3.14,"x",{"a":1},[2,3]]
=== array of arrays
[[1,2],[3,4],[5,6]]
---
[[1,2],[3,4],[5,6]]
=== whitespace variations (object)
{ "a" : 1 , "b" :
[ 1 , 2 , 3 ] ,
"c" :
{ "d" : "e" } }
---
{"a": 1, "b": [ 1 , 2 , 3 ], "c": { "d": "e" }}
=== whitespace variations (array)
[ 1 , { "x" : 2 } , [ 3 , 4 ] ]
---
[1, { "x": 2 }, [ 3, 4 ]]
=== whitespace after object
{}
---
{}
=== object with unicode and escapes mixed
{"text":"Line1\nLine2\u{263A}","emoji":"\u{1F680}","slash":"a/b","quote":"\""}
---
{"text":"Line1\nLine2\u263A","emoji":"🚀","slash":"a/b","quote":"\""}
=== array with empty structures nested
[[],{},[[],{}],{}]
---
[[],{},[[],{}],{}]
=== object trailing comma
{"a":1,}
---
{"a":1}
=== array trailing comma
[1,2,3,]
---
[1,2,3]
=== nested trailing commas
{"a":[1,2,], "b":{"x":1,},}
---
{"a":[1,2],"b":{"x":1}}
=== trailing comma after comment (object)
{
"a": 1, # keep a
}
---
{"a":1}
=== trailing comma after comment (array)
[
1, # first
]
---
[1]
=== array of objects with trailing commas
[
{"id":1,},
{"id":2,},
]
---
[{"id":1},{"id":2}]
=== object with last value array trailing comma
{"nums":[10,20,30,],}
---
{"nums":[10,20,30]}
=== single-element array with trailing comma
[42,]
---
[42]
=== single-pair object with trailing comma and spaces
{ "k": "v", }
---
{"k":"v"}
=== trailing comma and mixed whitespace
{
"x" : {"y" : [0,1,2,] ,} ,
}
---
{"x":{"y":[0,1,2]}}
=== full-line comment before object
# top-level note
{"a":1}
---
{"a":1}
=== multiple full-line comment before object + newlines
# comment 1
# comment 2
# comment 3
{"a":1}
---
{"a":1}
=== inline comment after pair
{"a":1 # apples
}
---
{"a":1}
=== inline comment after closing brace
{"a":1} # done
---
{"a":1}
=== comments between entries (object)
{
"a": 1, # first
# mid-line comment
"b": 2
}
---
{"a":1,"b":2}
=== comments between elements (array)
[
1, # one
# two incoming
2,
3 # last
]
---
[1,2,3]
=== comment between key and colon
{
"a" # key a
: 1
}
---
{"a":1}
=== comment between colon and value
{
"a": # value follows
1
}
---
{"a":1}
=== nested structure with comments
{
"obj": {
# inside obj
"k": "v" # end
},
"arr": [
# within array
1,2 # end
] # outer end
}
---
{"obj":{"k":"v"},"arr":[1,2]}
=== top-level number with trailing comment
123 # count
---
123
=== string containing hash (not a comment)
"# not a comment"
---
"# not a comment"
=== object with comment and trailing comma
{
"a": 1, # trailing comma ok
}
---
{"a":1}
=== array with comment and trailing comma
[
"x", # keep x
]
---
["x"]
=== trailing comma on both levels with comments
{
"inner": {
"list": [
1, # a
2, # b
], # list end
}, # inner end
}
---
{"inner":{"list":[1,2]}}
=== trailing comma after raw string with comment
{
"text": "Line1\nLine2", # trailing
}
---
{"text":"Line1\nLine2"}
=== comments around commas in array
[ 1 # a
, 2 # b
, 3 # c
]
---
[1,2,3]
=== array of objects with inline comments
[
{"a":1} # first
, {"a":2} # second
]
---
[{"a":1},{"a":2}]
=== comment at EOF
{"a":1} # EOF
---
{"a":1}
=== multiple comment at EOF
{"a":1} # comment 1
# comment 2
# comment 3
---
{"a":1}
=== object with newline separators
{"a":1
"b":2}
---
{"a":1,"b":2}
=== array with newline separators
[1
2
3]
---
[1,2,3]
=== nested with newline separators
{
"a": [
1
2
3
]
"b": {
"x": true
"y": null
}
}
---
{"a":[1,2,3],"b":{"x":true,"y":null}}
=== mix commas and newlines (array)
[0
1,2
3]
---
[0,1,2,3]
=== mix commas and newlines (object)
{"a":1
,"b":2
,"c":3}
---
{"a":1,"b":2,"c":3}
=== array of objects with newline separators
[
{"id":1}
{"id":2}
{"id":3}
]
---
[{"id":1},{"id":2},{"id":3}]
=== object with arrays using newline separators
{
"nums": [
10
20
30
]
"strs": [
"a"
"b"
]
}
---
{"nums":[10,20,30],"strs":["a","b"]}
=== array with comments and newline separators
[
1 # one
2 # two
3 # three
]
---
[1,2,3]
=== object with comments and newline separators
{
"a": 1 # first
"b": 2 # second
# end
}
---
{"a":1,"b":2}
=== consecutive newlines as separators (array)
[1
2
3]
---
[1,2,3]
=== consecutive newlines as separators (object)
{
"a":1
"b":2
}
---
{"a":1,"b":2}
=== array with trailing newline before close
[42
]
---
[42]
=== object with trailing newline before close
{
"k": "v"
}
---
{"k":"v"}
=== interleaved comments and newlines (array)
[
# start
100
# middle
200
# end
]
---
[100,200]
=== interleaved comments and newlines (object)
{
# start
"x": true
# mid
"y": false
}
---
{"x":true,"y":false}
=== array of arrays with newline separators
[
[1
2]
[3
4]
]
---
[[1,2],[3,4]]
=== object with special character keys (newline separators)
{
"a-b":1
"a b":2
"a:b":3
"a,b":4
}
---
{"a-b":1,"a b":2,"a:b":3,"a,b":4}
=== object with special keys
{
toString: 1
length: 2
}
---
{"toString": 1, "length": 2}
=== unicode values with newline separators
{
"text": "Привет"
"emoji": "😀"
"u": "\u{263A}"
}
---
{"text":"Привет","emoji":"😀","u":"\u263A"}
=== exponents with newline separators (keep numeric forms)
[
1e3
2E+2
7e-1
]
---
[1e3,2E+2,7e-1]
=== mixed whitespace + newline separators
{ "a":1
, "b": { "x":2
"y":3 }
, "c": [ 4
5
6 ] }
---
{"a":1,"b":{"x":2,"y":3},"c":[4,5,6]}
=== mixed whitespace + comment + newline separator + trailing comma
{ "a": 1 # comment
, }
---
{"a":1}
=== identifier keys basic
{a:1, b:2, c_3:3, foo-bar:4}
---
{"a":1,"b":2,"c_3":3,"foo-bar":4}
=== identifier digit-only key (string in result)
{1234:"id"}
---
{"1234":"id"}
=== identifier with leading underscore
{_private:true}
---
{"_private":true}
=== identifier with hyphen and underscore
{foo_bar-baz:42}
---
{"foo_bar-baz":42}
=== mix quoted and identifier keys
{foo:1,"bar":2,"baz-qux":3,quux_corge:4}
---
{"foo":1,"bar":2,"baz-qux":3,"quux_corge":4}
=== digit-only identifiers with leading zeros (kept as strings)
{0012:"pad",0:"zero"}
---
{"0012":"pad","0":"zero"}
=== reserved words as identifier keys (treated as strings)
{true:1,false:2,null:3}
---
{"true":1,"false":2,"null":3}
=== nested objects with identifier keys
{outer:{inner_key:{deep-n:7}}}
---
{"outer":{"inner_key":{"deep-n":7}}}
=== array of objects with identifier keys
[{id:1},{id:2},{user_name:"a-b"}]
---
[{"id":1},{"id":2},{"user_name":"a-b"}]
=== identifier keys with comments and trailing comma
{
a:1, # first
b:2, # second
}
---
{"a":1,"b":2}
=== identifier keys with newline separators (no commas)
{
a:1
b:2
c_3:3
}
---
{"a":1,"b":2,"c_3":3}
=== identifier keys with newline separators and arrays
{
items: [
1
2
3
]
meta: {count:3}
}
---
{"items":[1,2,3],"meta":{"count":3}}
=== identifier keys with trailing comma after comment and newline
{
key1: "v1", # comment
key2: "v2",
}
---
{"key1":"v1","key2":"v2"}
=== quoted unicode key next to identifier key
{"Привет":"hi", world:"мир"}
---
{"Привет":"hi","world":"мир"}
=== digit-only identifier keys nested
{data:{1234:"id",5678:"id2"}}
---
{"data":{"1234":"id","5678":"id2"}}
=== identifiers resembling exponents (letters + digits)
{e10:1, E10:2}
---
{"e10":1,"E10":2}
=== deep mix of quoted and identifier keys with newline separators
{
a:{b:{c:1
"d-e":2}}
arr:[
{x:1}
{y:2}
]
}
---
{"a":{"b":{"c":1,"d-e":2}},"arr":[{"x":1},{"y":2}]}
=== identifier keys with comments as separators
{
first: 1 # keep
second: 2 # keep
# end
}
---
{"first":1,"second":2}
=== identifier keys with mixed separators (commas + newlines)
{alpha:1
,beta:2
,gamma:3}
---
{"alpha":1,"beta":2,"gamma":3}
=== raw string basic
"""
The quick brown
fox jumps over
the lazy dog.
"""
---
"The quick brown\nfox jumps over\nthe lazy dog.\n"
=== raw string no trailing newline
"""
The quick brown
fox jumps over
the lazy dog."""
---
"The quick brown\nfox jumps over\nthe lazy dog."
=== leading spaces on first line are preserved
"""
indented first line
second line
"""
---
" indented first line\nsecond line\n"
=== whitespace preserved exactly (matches your example)
{
key: """
Roses are red,
Violets are blue;
"""
}
---
{"key":" Roses are red,\n Violets are blue;\n "}
=== escape sequences are literal (no interpretation)
"""
There is no escaping, so \n, \t, \u{0022} stay as-is.
"""
---
"There is no escaping, so \\n, \\t, \\u{0022} stay as-is.\n"
=== hash signs inside are content (not comments)
"""
# this is not a comment
still content
"""
---
"# this is not a comment\nstill content\n"
=== allow one or two quotes inside (not three)
"""
He said ""hi"" and "ok".
"""
---
"He said \"\"hi\"\" and \"ok\".\n"
=== single-line raw string
"""A raw string with "quotes" and '' inside."""
---
"A raw string with \"quotes\" and '' inside."
=== empty raw string -> empty string
"""
"""
---
""
=== single-space single-line raw string
""" """
---
" "
=== Windows-style path, backslashes preserved
"""
C:\Temp\new_folder\file.txt
"""
---
"C:\\Temp\\new_folder\\file.txt\n"
=== emoji and UTF-8 content
"""
😀 😁 😂
Привет мир
مرحبا بالعالم
"""
---
"😀 😁 😂\nПривет мир\nمرحبا بالعالم\n"
=== array of raw strings (newline as separators, no commas)
[
"""
a
b
"""
"""
c
d"""
]
---
["a\nb\n","c\nd"]
=== preserve interior blank lines
"""
top
middle
bottom
"""
---
"top\n\nmiddle\n\nbottom\n"
=== mix with comments and trailing comma (comments outside the string)
{
poem: """
Roses are red,
Violets are blue.
""" # keep poem
}
---
{"poem":"Roses are red,\nViolets are blue.\n"}
=== object with special keys
{
toString: 1
length: 2
}
---
{"toString": 1, "length": 2}
=== unicode escape: minimum code point U+0000 short form
"\u{0}"
---
"\u0000"
=== unicode escape: DEL via escape U+007F
"\u{7F}"
---
"\u007F"
=== unicode escape: last code point before surrogate range U+D7FF
"\u{D7FF}"
---
"\uD7FF"
=== unicode escape: first code point after surrogate range U+E000
"\u{E000}"
---
"\uE000"
=== unicode escape: last BMP code point U+FFFF
"\u{FFFF}"
---
"\uFFFF"
=== unicode escape: first supplementary plane code point U+10000
"\u{10000}"
---
"\uD800\uDC00"
=== unicode escape: leading zeros in hex digits
"\u{00263A}"
---
"\u263A"
=== individual escape: double quote
"\""
---
"\""
=== individual escape: backslash
"\\"
---
"\\"
=== individual escape: newline
"\n"
---
"\n"
=== individual escape: carriage return
"\r"
---
"\r"
=== individual escape: tab
"\t"
---
"\t"