Skip to content

Commit ad061bc

Browse files
authored
Merge pull request #13 from casperisfine/json-compat
Test and document compatibility with stdlib JSON
2 parents f8c57a3 + 0a8c6ef commit ad061bc

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ FastJsonparser.parse('{"one": 1, "two": 2}', symbolize_keys: false)
128128
FastJsonparser.parse("123: 1") # FastJsonparser::ParseError (parse error)
129129
```
130130

131+
### Known Incompatibilities with stdlib JSON
132+
133+
`FastJsonparser` behaves mostly like stdlib's `JSON`, but there are a few corner cases:
134+
135+
- `FastJsonparser` will use symbols for hash keys by default. You can pass `symbolize_names: false` to have strings instead like `JSON`.
136+
- `FastJsonparser` will raise on integers outside of the 64bits range (`-9223372036854775808..18446744073709551615`), `JSON` will parse them fine.
137+
- `FastJsonparser` will raise on invalid string escapings (`"\x15"`), `JSON` will often handle some of them.
138+
- `FastJsonparser` will raise on `/**/` comments. `JSON` will sometimes ignore them, sometimes raise.
139+
131140
### Example
132141

133142
```

test/fast_jsonparser_test.rb

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,86 @@ def test_load_many_batch_size
6969
FastJsonparser.load_many(f.path, batch_size: 6_000) {}
7070
end
7171
end
72+
73+
def test_compat_forward_slash_escape
74+
assert_compat('"\/"', "/")
75+
end
76+
77+
def test_compat_backward_slash_escape
78+
assert_compat('"\\\\"', '\\')
79+
end
80+
81+
def test_compat_illegal_escape
82+
refute_compat('["Illegal backslash escape: \x15"]', ["Illegal backslash escape: x15"], :raises)
83+
end
84+
85+
def test_compat_utf8
86+
assert_compat('"École"', "École")
87+
end
88+
89+
def test_compat_NaN_and_Infinity
90+
assert_compat('[NaN]', :raises)
91+
assert_compat('[Infinity]', :raises)
92+
assert_compat('[-Infinity]', :raises)
93+
end
94+
95+
def test_compat_hex_numbers
96+
assert_compat('[0x42]', :raises)
97+
end
98+
99+
def test_compat_weird_keys
100+
assert_compat('{[1]:2}', :raises)
101+
assert_compat('{{1:2}:2}', :raises)
102+
assert_compat('{null:2}', :raises)
103+
end
104+
105+
def test_compat_trailing_commas
106+
assert_compat('{1:2,}', :raises)
107+
assert_compat('{,,,,}', :raises)
108+
assert_compat('[1,]', :raises)
109+
assert_compat('[,,,,]', :raises)
110+
end
111+
112+
def test_compat_trailing_comments
113+
assert_compat('{} // comment', :raises)
114+
refute_compat('{} /* comment */', {}, :raises)
115+
assert_compat('{1:/*comment*/2}', :raises)
116+
refute_compat('{"a":/*comment*/"b"}', { "a" => "b" }, :raises)
117+
end
118+
119+
def test_compat_float_precision
120+
assert_compat '1.3553e142', 1.3553e142
121+
assert_compat '1.3553E142', 1.3553E142
122+
end
123+
124+
def test_compat_big_floats
125+
assert_compat '100000000000000000000000000000000000000000.0', 100000000000000000000000000000000000000000.0
126+
end
127+
128+
def test_compat_big_integers
129+
assert_compat '18446744073709551615', 18446744073709551615
130+
refute_compat '18446744073709551616', 18446744073709551616, :raises
131+
132+
assert_compat '-9223372036854775808', -9223372036854775808
133+
refute_compat '-9223372036854775809', -9223372036854775809, :raises
134+
end
135+
136+
private
137+
138+
def assert_compat(source, expected)
139+
assert_equal expected, parse(JSON, source), "This test is invalid"
140+
assert_equal expected, parse(FastJsonparser, source), "#{source.inspect} is not parsed the same by JSON and FastJsonparser"
141+
end
142+
143+
def refute_compat(source, expected, got)
144+
refute_equal expected, got
145+
assert_equal expected, parse(JSON, source)
146+
assert_equal got, parse(FastJsonparser, source)
147+
end
148+
149+
def parse(parser, source)
150+
parser.parse(source)
151+
rescue => error
152+
:raises
153+
end
72154
end

0 commit comments

Comments
 (0)