json 1.8.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +9 -12
- data/{CHANGES → CHANGES.md} +219 -90
- data/Gemfile +10 -6
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +201 -134
- data/Rakefile +35 -113
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +255 -101
- data/ext/json/ext/generator/generator.h +12 -4
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +410 -462
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +166 -181
- data/ext/json/extconf.rb +1 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +39 -36
- data/java/src/json/ext/GeneratorMethods.java +1 -2
- data/java/src/json/ext/GeneratorService.java +1 -2
- data/java/src/json/ext/GeneratorState.java +33 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +146 -417
- data/java/src/json/ext/Parser.rl +62 -126
- data/java/src/json/ext/ParserService.java +1 -2
- data/java/src/json/ext/RuntimeInfo.java +1 -6
- data/java/src/json/ext/StringDecoder.java +1 -2
- data/java/src/json/ext/StringEncoder.java +13 -2
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +22 -7
- data/json.gemspec +0 -0
- data/json_pure.gemspec +22 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -3
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +350 -152
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +83 -126
- data/lib/json/pure/parser.rb +62 -84
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
- data/tests/json_common_interface_test.rb +169 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +497 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/test_helper.rb +17 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +47 -53
- data/COPYING +0 -58
- data/GPL +0 -340
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
+
# frozen_string_literal: false
|
3
4
|
|
4
|
-
require '
|
5
|
-
require File.join(File.dirname(__FILE__), 'setup_variant')
|
5
|
+
require 'test_helper'
|
6
6
|
|
7
|
-
class
|
7
|
+
class JSONGeneratorTest < Test::Unit::TestCase
|
8
8
|
include JSON
|
9
9
|
|
10
10
|
def setup
|
@@ -40,25 +40,67 @@ class TestJSONGenerate < Test::Unit::TestCase
|
|
40
40
|
EOT
|
41
41
|
end
|
42
42
|
|
43
|
+
def silence
|
44
|
+
v = $VERBOSE
|
45
|
+
$VERBOSE = nil
|
46
|
+
yield
|
47
|
+
ensure
|
48
|
+
$VERBOSE = v
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_remove_const_segv
|
52
|
+
stress = GC.stress
|
53
|
+
const = JSON::SAFE_STATE_PROTOTYPE.dup
|
54
|
+
|
55
|
+
bignum_too_long_to_embed_as_string = 1234567890123456789012345
|
56
|
+
expect = bignum_too_long_to_embed_as_string.to_s
|
57
|
+
GC.stress = true
|
58
|
+
|
59
|
+
10.times do |i|
|
60
|
+
tmp = bignum_too_long_to_embed_as_string.to_json
|
61
|
+
raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
|
62
|
+
end
|
63
|
+
|
64
|
+
silence do
|
65
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, nil
|
66
|
+
end
|
67
|
+
|
68
|
+
10.times do |i|
|
69
|
+
assert_raise TypeError do
|
70
|
+
bignum_too_long_to_embed_as_string.to_json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
ensure
|
74
|
+
GC.stress = stress
|
75
|
+
silence do
|
76
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, const
|
77
|
+
end
|
78
|
+
end if JSON.const_defined?("Ext") && RUBY_ENGINE != 'jruby'
|
79
|
+
|
43
80
|
def test_generate
|
44
81
|
json = generate(@hash)
|
45
|
-
assert_equal(
|
82
|
+
assert_equal(parse(@json2), parse(json))
|
46
83
|
json = JSON[@hash]
|
47
|
-
assert_equal(
|
84
|
+
assert_equal(parse(@json2), parse(json))
|
48
85
|
parsed_json = parse(json)
|
49
86
|
assert_equal(@hash, parsed_json)
|
50
87
|
json = generate({1=>2})
|
51
88
|
assert_equal('{"1":2}', json)
|
52
89
|
parsed_json = parse(json)
|
53
90
|
assert_equal({"1"=>2}, parsed_json)
|
54
|
-
|
55
|
-
assert_equal '666', generate(666, :quirks_mode => true)
|
91
|
+
assert_equal '666', generate(666)
|
56
92
|
end
|
57
93
|
|
58
94
|
def test_generate_pretty
|
95
|
+
json = pretty_generate({})
|
96
|
+
assert_equal(<<'EOT'.chomp, json)
|
97
|
+
{
|
98
|
+
}
|
99
|
+
EOT
|
59
100
|
json = pretty_generate(@hash)
|
60
|
-
# hashes aren't (insertion) ordered on every ruby implementation
|
61
|
-
assert_equal(
|
101
|
+
# hashes aren't (insertion) ordered on every ruby implementation
|
102
|
+
# assert_equal(@json3, json)
|
103
|
+
assert_equal(parse(@json3), parse(json))
|
62
104
|
parsed_json = parse(json)
|
63
105
|
assert_equal(@hash, parsed_json)
|
64
106
|
json = pretty_generate({1=>2})
|
@@ -69,8 +111,7 @@ EOT
|
|
69
111
|
EOT
|
70
112
|
parsed_json = parse(json)
|
71
113
|
assert_equal({"1"=>2}, parsed_json)
|
72
|
-
|
73
|
-
assert_equal '666', pretty_generate(666, :quirks_mode => true)
|
114
|
+
assert_equal '666', pretty_generate(666)
|
74
115
|
end
|
75
116
|
|
76
117
|
def test_generate_custom
|
@@ -88,30 +129,26 @@ EOT
|
|
88
129
|
|
89
130
|
def test_fast_generate
|
90
131
|
json = fast_generate(@hash)
|
91
|
-
assert_equal(
|
132
|
+
assert_equal(parse(@json2), parse(json))
|
92
133
|
parsed_json = parse(json)
|
93
134
|
assert_equal(@hash, parsed_json)
|
94
135
|
json = fast_generate({1=>2})
|
95
136
|
assert_equal('{"1":2}', json)
|
96
137
|
parsed_json = parse(json)
|
97
138
|
assert_equal({"1"=>2}, parsed_json)
|
98
|
-
|
99
|
-
assert_equal '666', fast_generate(666, :quirks_mode => true)
|
139
|
+
assert_equal '666', fast_generate(666)
|
100
140
|
end
|
101
141
|
|
102
142
|
def test_own_state
|
103
143
|
state = State.new
|
104
144
|
json = generate(@hash, state)
|
105
|
-
assert_equal(
|
145
|
+
assert_equal(parse(@json2), parse(json))
|
106
146
|
parsed_json = parse(json)
|
107
147
|
assert_equal(@hash, parsed_json)
|
108
148
|
json = generate({1=>2}, state)
|
109
149
|
assert_equal('{"1":2}', json)
|
110
150
|
parsed_json = parse(json)
|
111
151
|
assert_equal({"1"=>2}, parsed_json)
|
112
|
-
assert_raise(GeneratorError) { generate(666, state) }
|
113
|
-
state.quirks_mode = true
|
114
|
-
assert state.quirks_mode?
|
115
152
|
assert_equal '666', generate(666, state)
|
116
153
|
end
|
117
154
|
|
@@ -123,12 +160,12 @@ EOT
|
|
123
160
|
assert s[:check_circular?]
|
124
161
|
h = { 1=>2 }
|
125
162
|
h[3] = h
|
126
|
-
|
127
|
-
|
163
|
+
assert_raise(JSON::NestingError) { generate(h) }
|
164
|
+
assert_raise(JSON::NestingError) { generate(h, s) }
|
128
165
|
s = JSON.state.new
|
129
166
|
a = [ 1, 2 ]
|
130
167
|
a << a
|
131
|
-
|
168
|
+
assert_raise(JSON::NestingError) { generate(a, s) }
|
132
169
|
assert s.check_circular?
|
133
170
|
assert s[:check_circular?]
|
134
171
|
end
|
@@ -140,8 +177,8 @@ EOT
|
|
140
177
|
:array_nl => "\n",
|
141
178
|
:ascii_only => false,
|
142
179
|
:buffer_initial_length => 1024,
|
143
|
-
:quirks_mode => false,
|
144
180
|
:depth => 0,
|
181
|
+
:escape_slash => false,
|
145
182
|
:indent => " ",
|
146
183
|
:max_nesting => 100,
|
147
184
|
:object_nl => "\n",
|
@@ -157,8 +194,8 @@ EOT
|
|
157
194
|
:array_nl => "",
|
158
195
|
:ascii_only => false,
|
159
196
|
:buffer_initial_length => 1024,
|
160
|
-
:quirks_mode => false,
|
161
197
|
:depth => 0,
|
198
|
+
:escape_slash => false,
|
162
199
|
:indent => "",
|
163
200
|
:max_nesting => 100,
|
164
201
|
:object_nl => "",
|
@@ -174,8 +211,8 @@ EOT
|
|
174
211
|
:array_nl => "",
|
175
212
|
:ascii_only => false,
|
176
213
|
:buffer_initial_length => 1024,
|
177
|
-
:quirks_mode => false,
|
178
214
|
:depth => 0,
|
215
|
+
:escape_slash => false,
|
179
216
|
:indent => "",
|
180
217
|
:max_nesting => 0,
|
181
218
|
:object_nl => "",
|
@@ -185,34 +222,34 @@ EOT
|
|
185
222
|
end
|
186
223
|
|
187
224
|
def test_allow_nan
|
188
|
-
|
225
|
+
assert_raise(GeneratorError) { generate([JSON::NaN]) }
|
189
226
|
assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
|
190
|
-
|
191
|
-
|
227
|
+
assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
|
228
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
|
192
229
|
assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
|
193
|
-
|
230
|
+
assert_raise(GeneratorError) { generate([JSON::Infinity]) }
|
194
231
|
assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
|
195
|
-
|
196
|
-
|
232
|
+
assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
|
233
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
|
197
234
|
assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
|
198
|
-
|
235
|
+
assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
|
199
236
|
assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
|
200
|
-
|
201
|
-
|
237
|
+
assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
|
238
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
|
202
239
|
assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
|
203
240
|
end
|
204
241
|
|
205
242
|
def test_depth
|
206
243
|
ary = []; ary << ary
|
207
244
|
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
208
|
-
|
245
|
+
assert_raise(JSON::NestingError) { generate(ary) }
|
209
246
|
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
210
247
|
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
211
|
-
|
248
|
+
assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
|
212
249
|
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
213
250
|
s = JSON.state.new
|
214
251
|
assert_equal 0, s.depth
|
215
|
-
|
252
|
+
assert_raise(JSON::NestingError) { ary.to_json(s) }
|
216
253
|
assert_equal 100, s.depth
|
217
254
|
end
|
218
255
|
|
@@ -285,12 +322,13 @@ EOT
|
|
285
322
|
if defined?(JSON::Ext::Generator)
|
286
323
|
def test_broken_bignum # [ruby-core:38867]
|
287
324
|
pid = fork do
|
288
|
-
|
325
|
+
x = 1 << 64
|
326
|
+
x.class.class_eval do
|
289
327
|
def to_s
|
290
328
|
end
|
291
329
|
end
|
292
330
|
begin
|
293
|
-
JSON::Ext::Generator::State.new.generate(
|
331
|
+
JSON::Ext::Generator::State.new.generate(x)
|
294
332
|
exit 1
|
295
333
|
rescue TypeError
|
296
334
|
exit 0
|
@@ -331,7 +369,64 @@ EOT
|
|
331
369
|
|
332
370
|
def test_json_generate
|
333
371
|
assert_raise JSON::GeneratorError do
|
334
|
-
assert_equal true,
|
372
|
+
assert_equal true, generate(["\xea"])
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def test_nesting
|
377
|
+
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
|
378
|
+
too_deep_ary = eval too_deep
|
379
|
+
assert_raise(JSON::NestingError) { generate too_deep_ary }
|
380
|
+
assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
|
381
|
+
ok = generate too_deep_ary, :max_nesting => 101
|
382
|
+
assert_equal too_deep, ok
|
383
|
+
ok = generate too_deep_ary, :max_nesting => nil
|
384
|
+
assert_equal too_deep, ok
|
385
|
+
ok = generate too_deep_ary, :max_nesting => false
|
386
|
+
assert_equal too_deep, ok
|
387
|
+
ok = generate too_deep_ary, :max_nesting => 0
|
388
|
+
assert_equal too_deep, ok
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_backslash
|
392
|
+
data = [ '\\.(?i:gif|jpe?g|png)$' ]
|
393
|
+
json = '["\\\\.(?i:gif|jpe?g|png)$"]'
|
394
|
+
assert_equal json, generate(data)
|
395
|
+
#
|
396
|
+
data = [ '\\"' ]
|
397
|
+
json = '["\\\\\""]'
|
398
|
+
assert_equal json, generate(data)
|
399
|
+
#
|
400
|
+
data = [ '/' ]
|
401
|
+
json = '["/"]'
|
402
|
+
assert_equal json, generate(data)
|
403
|
+
#
|
404
|
+
data = [ '/' ]
|
405
|
+
json = '["\/"]'
|
406
|
+
assert_equal json, generate(data, :escape_slash => true)
|
407
|
+
#
|
408
|
+
data = ['"']
|
409
|
+
json = '["\""]'
|
410
|
+
assert_equal json, generate(data)
|
411
|
+
#
|
412
|
+
data = ["'"]
|
413
|
+
json = '["\\\'"]'
|
414
|
+
assert_equal '["\'"]', generate(data)
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_string_subclass
|
418
|
+
s = Class.new(String) do
|
419
|
+
def to_s; self; end
|
420
|
+
undef to_json
|
421
|
+
end
|
422
|
+
assert_nothing_raised(SystemStackError) do
|
423
|
+
assert_equal '["foo"]', JSON.generate([s.new('foo')])
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
if defined?(Encoding)
|
428
|
+
def test_nonutf8_encoding
|
429
|
+
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
|
335
430
|
end
|
336
431
|
end
|
337
432
|
end
|
@@ -1,9 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#frozen_string_literal: false
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
|
5
|
-
require File.join(File.dirname(__FILE__), 'setup_variant')
|
6
|
-
class TestJSONGenericObject < Test::Unit::TestCase
|
4
|
+
class JSONGenericObjectTest < Test::Unit::TestCase
|
7
5
|
include JSON
|
8
6
|
|
9
7
|
def setup
|
@@ -26,11 +24,20 @@ class TestJSONGenericObject < Test::Unit::TestCase
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def test_parse_json
|
29
|
-
assert_kind_of Hash,
|
27
|
+
assert_kind_of Hash,
|
28
|
+
JSON(
|
29
|
+
'{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
|
30
|
+
:create_additions => true
|
31
|
+
)
|
30
32
|
switch_json_creatable do
|
31
|
-
assert_equal @go, l =
|
33
|
+
assert_equal @go, l =
|
34
|
+
JSON(
|
35
|
+
'{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
|
36
|
+
:create_additions => true
|
37
|
+
)
|
32
38
|
assert_equal 1, l.a
|
33
|
-
assert_equal @go,
|
39
|
+
assert_equal @go,
|
40
|
+
l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
|
34
41
|
assert_equal 1, l.a
|
35
42
|
assert_equal GenericObject[:a => GenericObject[:b => 2]],
|
36
43
|
l = JSON('{ "a": { "b": 2 } }', :object_class => GenericObject)
|