json 2.0.3 → 2.5.1
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/CHANGES.md +66 -0
- data/Gemfile +1 -3
- data/LICENSE +56 -0
- data/README.md +54 -21
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +229 -54
- data/ext/json/ext/generator/generator.h +5 -3
- data/ext/json/ext/parser/extconf.rb +25 -0
- data/ext/json/ext/parser/parser.c +180 -85
- data/ext/json/ext/parser/parser.h +2 -0
- data/ext/json/ext/parser/parser.rl +104 -9
- data/ext/json/extconf.rb +1 -0
- data/json.gemspec +0 -0
- data/lib/json/add/bigdecimal.rb +2 -2
- data/lib/json/add/complex.rb +2 -3
- data/lib/json/add/ostruct.rb +1 -1
- data/lib/json/add/rational.rb +2 -3
- data/lib/json/add/regexp.rb +2 -2
- data/lib/json/add/set.rb +29 -0
- data/lib/json/common.rb +372 -125
- data/lib/json/pure/generator.rb +31 -10
- data/lib/json/pure/parser.rb +35 -5
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +549 -29
- data/tests/fixtures/fail29.json +1 -0
- data/tests/fixtures/fail30.json +1 -0
- data/tests/fixtures/fail31.json +1 -0
- data/tests/fixtures/fail32.json +1 -0
- data/tests/json_addition_test.rb +6 -0
- data/tests/json_common_interface_test.rb +47 -4
- data/tests/json_encoding_test.rb +2 -0
- data/tests/json_fixtures_test.rb +9 -1
- data/tests/json_generator_test.rb +30 -8
- data/tests/json_parser_test.rb +43 -12
- data/tests/lib/core_assertions.rb +763 -0
- data/tests/lib/envutil.rb +365 -0
- data/tests/lib/find_executable.rb +22 -0
- data/tests/lib/helper.rb +4 -0
- data/tests/ractor_test.rb +30 -0
- data/tests/test_helper.rb +3 -7
- metadata +31 -44
- data/.gitignore +0 -17
- data/.travis.yml +0 -19
- data/README-json-jruby.md +0 -33
- data/Rakefile +0 -408
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -166
- data/java/src/json/ext/Generator.java +0 -443
- data/java/src/json/ext/GeneratorMethods.java +0 -231
- data/java/src/json/ext/GeneratorService.java +0 -42
- data/java/src/json/ext/GeneratorState.java +0 -490
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2347
- data/java/src/json/ext/Parser.rl +0 -878
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -116
- data/java/src/json/ext/StringDecoder.java +0 -166
- data/java/src/json/ext/StringEncoder.java +0 -111
- data/java/src/json/ext/Utils.java +0 -88
- data/json-java.gemspec +0 -38
- data/json_pure.gemspec +0 -38
- data/references/rfc7159.txt +0 -899
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -131
- data/tools/server.rb +0 -62
@@ -27,15 +27,15 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_parser
|
30
|
-
assert_match
|
30
|
+
assert_match(/::Parser\z/, JSON.parser.name)
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_generator
|
34
|
-
assert_match
|
34
|
+
assert_match(/::Generator\z/, JSON.generator.name)
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_state
|
38
|
-
assert_match
|
38
|
+
assert_match(/::Generator::State\z/, JSON.state.name)
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_create_id
|
@@ -56,7 +56,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_parse_bang
|
59
|
-
assert_equal [ 1,
|
59
|
+
assert_equal [ 1, Infinity, 3, ], JSON.parse!('[ 1, Infinity, 3 ]')
|
60
60
|
end
|
61
61
|
|
62
62
|
def test_generate
|
@@ -123,4 +123,47 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
123
123
|
assert_equal @json, JSON(@hash)
|
124
124
|
assert_equal @hash, JSON(@json)
|
125
125
|
end
|
126
|
+
|
127
|
+
def test_load_file
|
128
|
+
test_load_shared(:load_file)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_load_file!
|
132
|
+
test_load_shared(:load_file!)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_load_file_with_option
|
136
|
+
test_load_file_with_option_shared(:load_file)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_load_file_with_option!
|
140
|
+
test_load_file_with_option_shared(:load_file!)
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
def test_load_shared(method_name)
|
146
|
+
temp_file_containing(@json) do |filespec|
|
147
|
+
assert_equal JSON.public_send(method_name, filespec), @hash
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_load_file_with_option_shared(method_name)
|
152
|
+
temp_file_containing(@json) do |filespec|
|
153
|
+
parsed_object = JSON.public_send(method_name, filespec, symbolize_names: true)
|
154
|
+
key_classes = parsed_object.keys.map(&:class)
|
155
|
+
assert_include(key_classes, Symbol)
|
156
|
+
assert_not_include(key_classes, String)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def temp_file_containing(text, file_prefix = '')
|
161
|
+
raise "This method must be called with a code block." unless block_given?
|
162
|
+
|
163
|
+
Tempfile.create(file_prefix) do |file|
|
164
|
+
file << text
|
165
|
+
file.close
|
166
|
+
yield file.path
|
167
|
+
end
|
168
|
+
end
|
126
169
|
end
|
data/tests/json_encoding_test.rb
CHANGED
@@ -79,6 +79,8 @@ class JSONEncodingTest < Test::Unit::TestCase
|
|
79
79
|
json = '["\ud840\udc01"]'
|
80
80
|
assert_equal json, generate(utf8, :ascii_only => true)
|
81
81
|
assert_equal utf8, parse(json)
|
82
|
+
assert_raise(JSON::ParserError) { parse('"\u"') }
|
83
|
+
assert_raise(JSON::ParserError) { parse('"\ud800"') }
|
82
84
|
end
|
83
85
|
|
84
86
|
def test_chars
|
data/tests/json_fixtures_test.rb
CHANGED
@@ -3,13 +3,14 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class JSONFixturesTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}
|
6
|
+
fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
|
7
7
|
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
|
8
8
|
@passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
9
9
|
@failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_passing
|
13
|
+
verbose_bak, $VERBOSE = $VERBOSE, nil
|
13
14
|
for name, source in @passed
|
14
15
|
begin
|
15
16
|
assert JSON.parse(source),
|
@@ -19,6 +20,8 @@ class JSONFixturesTest < Test::Unit::TestCase
|
|
19
20
|
raise e
|
20
21
|
end
|
21
22
|
end
|
23
|
+
ensure
|
24
|
+
$VERBOSE = verbose_bak
|
22
25
|
end
|
23
26
|
|
24
27
|
def test_failing
|
@@ -29,4 +32,9 @@ class JSONFixturesTest < Test::Unit::TestCase
|
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
35
|
+
|
36
|
+
def test_sanity
|
37
|
+
assert(@passed.size > 5)
|
38
|
+
assert(@failed.size > 20)
|
39
|
+
end
|
32
40
|
end
|
@@ -40,6 +40,14 @@ class JSONGeneratorTest < 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
|
+
|
43
51
|
def test_generate
|
44
52
|
json = generate(@hash)
|
45
53
|
assert_equal(parse(@json2), parse(json))
|
@@ -55,6 +63,11 @@ EOT
|
|
55
63
|
end
|
56
64
|
|
57
65
|
def test_generate_pretty
|
66
|
+
json = pretty_generate({})
|
67
|
+
assert_equal(<<'EOT'.chomp, json)
|
68
|
+
{
|
69
|
+
}
|
70
|
+
EOT
|
58
71
|
json = pretty_generate(@hash)
|
59
72
|
# hashes aren't (insertion) ordered on every ruby implementation
|
60
73
|
# assert_equal(@json3, json)
|
@@ -129,13 +142,14 @@ EOT
|
|
129
142
|
end
|
130
143
|
|
131
144
|
def test_pretty_state
|
132
|
-
state =
|
145
|
+
state = JSON.create_pretty_state
|
133
146
|
assert_equal({
|
134
147
|
:allow_nan => false,
|
135
148
|
:array_nl => "\n",
|
136
149
|
:ascii_only => false,
|
137
150
|
:buffer_initial_length => 1024,
|
138
151
|
:depth => 0,
|
152
|
+
:escape_slash => false,
|
139
153
|
:indent => " ",
|
140
154
|
:max_nesting => 100,
|
141
155
|
:object_nl => "\n",
|
@@ -145,13 +159,14 @@ EOT
|
|
145
159
|
end
|
146
160
|
|
147
161
|
def test_safe_state
|
148
|
-
state =
|
162
|
+
state = JSON::State.new
|
149
163
|
assert_equal({
|
150
164
|
:allow_nan => false,
|
151
165
|
:array_nl => "",
|
152
166
|
:ascii_only => false,
|
153
167
|
:buffer_initial_length => 1024,
|
154
168
|
:depth => 0,
|
169
|
+
:escape_slash => false,
|
155
170
|
:indent => "",
|
156
171
|
:max_nesting => 100,
|
157
172
|
:object_nl => "",
|
@@ -161,13 +176,14 @@ EOT
|
|
161
176
|
end
|
162
177
|
|
163
178
|
def test_fast_state
|
164
|
-
state =
|
179
|
+
state = JSON.create_fast_state
|
165
180
|
assert_equal({
|
166
181
|
:allow_nan => false,
|
167
182
|
:array_nl => "",
|
168
183
|
:ascii_only => false,
|
169
184
|
:buffer_initial_length => 1024,
|
170
185
|
:depth => 0,
|
186
|
+
:escape_slash => false,
|
171
187
|
:indent => "",
|
172
188
|
:max_nesting => 0,
|
173
189
|
:object_nl => "",
|
@@ -196,12 +212,8 @@ EOT
|
|
196
212
|
|
197
213
|
def test_depth
|
198
214
|
ary = []; ary << ary
|
199
|
-
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
200
215
|
assert_raise(JSON::NestingError) { generate(ary) }
|
201
|
-
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
202
|
-
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
203
216
|
assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
|
204
|
-
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
205
217
|
s = JSON.state.new
|
206
218
|
assert_equal 0, s.depth
|
207
219
|
assert_raise(JSON::NestingError) { ary.to_json(s) }
|
@@ -220,7 +232,7 @@ EOT
|
|
220
232
|
end
|
221
233
|
|
222
234
|
def test_gc
|
223
|
-
if respond_to?(:assert_in_out_err)
|
235
|
+
if respond_to?(:assert_in_out_err) && !(RUBY_PLATFORM =~ /java/)
|
224
236
|
assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
|
225
237
|
bignum_too_long_to_embed_as_string = 1234567890123456789012345
|
226
238
|
expect = bignum_too_long_to_embed_as_string.to_s
|
@@ -356,6 +368,10 @@ EOT
|
|
356
368
|
json = '["/"]'
|
357
369
|
assert_equal json, generate(data)
|
358
370
|
#
|
371
|
+
data = [ '/' ]
|
372
|
+
json = '["\/"]'
|
373
|
+
assert_equal json, generate(data, :escape_slash => true)
|
374
|
+
#
|
359
375
|
data = ['"']
|
360
376
|
json = '["\""]'
|
361
377
|
assert_equal json, generate(data)
|
@@ -374,4 +390,10 @@ EOT
|
|
374
390
|
assert_equal '["foo"]', JSON.generate([s.new('foo')])
|
375
391
|
end
|
376
392
|
end
|
393
|
+
|
394
|
+
if defined?(Encoding)
|
395
|
+
def test_nonutf8_encoding
|
396
|
+
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
|
397
|
+
end
|
398
|
+
end
|
377
399
|
end
|
data/tests/json_parser_test.rb
CHANGED
@@ -4,6 +4,7 @@ require 'test_helper'
|
|
4
4
|
require 'stringio'
|
5
5
|
require 'tempfile'
|
6
6
|
require 'ostruct'
|
7
|
+
require 'bigdecimal'
|
7
8
|
|
8
9
|
class JSONParserTest < Test::Unit::TestCase
|
9
10
|
include JSON
|
@@ -90,22 +91,27 @@ class JSONParserTest < Test::Unit::TestCase
|
|
90
91
|
assert_raise(JSON::ParserError) { parse('+23') }
|
91
92
|
assert_raise(JSON::ParserError) { parse('.23') }
|
92
93
|
assert_raise(JSON::ParserError) { parse('023') }
|
93
|
-
assert_equal
|
94
|
-
assert_equal
|
95
|
-
assert_equal_float
|
96
|
-
assert_equal_float
|
97
|
-
assert_equal_float
|
98
|
-
assert_equal_float
|
99
|
-
assert_equal_float
|
100
|
-
assert_equal_float
|
101
|
-
assert_equal_float
|
102
|
-
assert_equal_float
|
94
|
+
assert_equal(23, parse('23'))
|
95
|
+
assert_equal(-23, parse('-23'))
|
96
|
+
assert_equal_float(3.141, parse('3.141'))
|
97
|
+
assert_equal_float(-3.141, parse('-3.141'))
|
98
|
+
assert_equal_float(3.141, parse('3141e-3'))
|
99
|
+
assert_equal_float(3.141, parse('3141.1e-3'))
|
100
|
+
assert_equal_float(3.141, parse('3141E-3'))
|
101
|
+
assert_equal_float(3.141, parse('3141.0E-3'))
|
102
|
+
assert_equal_float(-3.141, parse('-3141.0e-3'))
|
103
|
+
assert_equal_float(-3.141, parse('-3141e-3'))
|
103
104
|
assert_raise(ParserError) { parse('NaN') }
|
104
105
|
assert parse('NaN', :allow_nan => true).nan?
|
105
106
|
assert_raise(ParserError) { parse('Infinity') }
|
106
|
-
assert_equal
|
107
|
+
assert_equal(1.0/0, parse('Infinity', :allow_nan => true))
|
107
108
|
assert_raise(ParserError) { parse('-Infinity') }
|
108
|
-
assert_equal
|
109
|
+
assert_equal(-1.0/0, parse('-Infinity', :allow_nan => true))
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_parse_bigdecimals
|
113
|
+
assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
|
114
|
+
assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
|
109
115
|
end
|
110
116
|
|
111
117
|
if Array.method_defined?(:permutation)
|
@@ -212,6 +218,17 @@ class JSONParserTest < Test::Unit::TestCase
|
|
212
218
|
end
|
213
219
|
end
|
214
220
|
|
221
|
+
def test_freeze
|
222
|
+
assert_predicate parse('{}', :freeze => true), :frozen?
|
223
|
+
assert_predicate parse('[]', :freeze => true), :frozen?
|
224
|
+
assert_predicate parse('"foo"', :freeze => true), :frozen?
|
225
|
+
|
226
|
+
if string_deduplication_available?
|
227
|
+
assert_same(-'foo', parse('"foo"', :freeze => true))
|
228
|
+
assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
215
232
|
def test_parse_comments
|
216
233
|
json = <<EOT
|
217
234
|
{
|
@@ -287,6 +304,10 @@ EOT
|
|
287
304
|
json = '["\\\'"]'
|
288
305
|
data = ["'"]
|
289
306
|
assert_equal data, parse(json)
|
307
|
+
|
308
|
+
json = '["\/"]'
|
309
|
+
data = [ '/' ]
|
310
|
+
assert_equal data, parse(json)
|
290
311
|
end
|
291
312
|
|
292
313
|
class SubArray < Array
|
@@ -458,6 +479,16 @@ EOT
|
|
458
479
|
|
459
480
|
private
|
460
481
|
|
482
|
+
def string_deduplication_available?
|
483
|
+
r1 = rand.to_s
|
484
|
+
r2 = r1.dup
|
485
|
+
begin
|
486
|
+
(-r1).equal?(-r2)
|
487
|
+
rescue NoMethodError
|
488
|
+
false # No String#-@
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
461
492
|
def assert_equal_float(expected, actual, delta = 1e-2)
|
462
493
|
Array === expected and expected = expected.first
|
463
494
|
Array === actual and actual = actual.first
|