json 1.8.2 → 2.3.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/.gitignore +2 -0
- data/.travis.yml +11 -9
- data/{CHANGES → CHANGES.md} +220 -89
- data/Gemfile +10 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +204 -137
- data/Rakefile +35 -113
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +215 -110
- data/ext/json/ext/generator/generator.h +18 -5
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +422 -508
- data/ext/json/ext/parser/parser.h +15 -8
- data/ext/json/ext/parser/parser.rl +151 -200
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +44 -22
- 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 +3 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +132 -415
- data/java/src/json/ext/Parser.rl +48 -124
- 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 +5 -0
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +16 -2
- data/json.gemspec +0 -0
- data/json_pure.gemspec +22 -29
- data/lib/json.rb +379 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -3
- 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 -2
- 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 +335 -128
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +64 -127
- data/lib/json/pure/parser.rb +42 -82
- data/lib/json/version.rb +2 -1
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
- data/tests/json_common_interface_test.rb +126 -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} +10 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +472 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +6 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +46 -53
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- 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/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
@@ -0,0 +1 @@
|
|
1
|
+
"A JSON payload should be an object or array, not a string."
|
@@ -1,16 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'test/unit'
|
5
|
-
require File.join(File.dirname(__FILE__), 'setup_variant')
|
1
|
+
#frozen_string_literal: false
|
2
|
+
require 'test_helper'
|
6
3
|
require 'json/add/core'
|
7
4
|
require 'json/add/complex'
|
8
5
|
require 'json/add/rational'
|
9
6
|
require 'json/add/bigdecimal'
|
10
7
|
require 'json/add/ostruct'
|
8
|
+
require 'json/add/set'
|
11
9
|
require 'date'
|
12
10
|
|
13
|
-
class
|
11
|
+
class JSONAdditionTest < Test::Unit::TestCase
|
14
12
|
include JSON
|
15
13
|
|
16
14
|
class A
|
@@ -64,7 +62,7 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
64
62
|
|
65
63
|
def to_json(*args)
|
66
64
|
{
|
67
|
-
'json_class' => '
|
65
|
+
'json_class' => 'JSONAdditionTest::Nix',
|
68
66
|
}.to_json(*args)
|
69
67
|
end
|
70
68
|
end
|
@@ -73,7 +71,7 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
73
71
|
a = A.new(666)
|
74
72
|
assert A.json_creatable?
|
75
73
|
json = generate(a)
|
76
|
-
a_again =
|
74
|
+
a_again = parse(json, :create_additions => true)
|
77
75
|
assert_kind_of a.class, a_again
|
78
76
|
assert_equal a, a_again
|
79
77
|
end
|
@@ -82,7 +80,7 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
82
80
|
a = A.new(666)
|
83
81
|
assert A.json_creatable?
|
84
82
|
json = generate(a)
|
85
|
-
a_hash =
|
83
|
+
a_hash = parse(json)
|
86
84
|
assert_kind_of Hash, a_hash
|
87
85
|
end
|
88
86
|
|
@@ -90,13 +88,13 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
90
88
|
a = A.new(666)
|
91
89
|
assert A.json_creatable?
|
92
90
|
json = generate(a)
|
93
|
-
a_again =
|
91
|
+
a_again = parse(json, :create_additions => true)
|
94
92
|
assert_kind_of a.class, a_again
|
95
93
|
assert_equal a, a_again
|
96
|
-
a_hash =
|
94
|
+
a_hash = parse(json, :create_additions => false)
|
97
95
|
assert_kind_of Hash, a_hash
|
98
96
|
assert_equal(
|
99
|
-
{"args"=>[666], "json_class"=>"
|
97
|
+
{"args"=>[666], "json_class"=>"JSONAdditionTest::A"}.sort_by { |k,| k },
|
100
98
|
a_hash.sort_by { |k,| k }
|
101
99
|
)
|
102
100
|
end
|
@@ -105,14 +103,14 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
105
103
|
b = B.new
|
106
104
|
assert !B.json_creatable?
|
107
105
|
json = generate(b)
|
108
|
-
assert_equal({ "json_class"=>"
|
106
|
+
assert_equal({ "json_class"=>"JSONAdditionTest::B" }, parse(json))
|
109
107
|
end
|
110
108
|
|
111
109
|
def test_extended_json_fail2
|
112
110
|
c = C.new
|
113
111
|
assert !C.json_creatable?
|
114
112
|
json = generate(c)
|
115
|
-
|
113
|
+
assert_raise(ArgumentError, NameError) { parse(json, :create_additions => true) }
|
116
114
|
end
|
117
115
|
|
118
116
|
def test_raw_strings
|
@@ -130,7 +128,7 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
130
128
|
assert_match(/\A\{.*\}\z/, json)
|
131
129
|
assert_match(/"json_class":"String"/, json)
|
132
130
|
assert_match(/"raw":\[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\]/, json)
|
133
|
-
raw_again =
|
131
|
+
raw_again = parse(json, :create_additions => true)
|
134
132
|
assert_equal raw, raw_again
|
135
133
|
end
|
136
134
|
|
@@ -151,7 +149,7 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
151
149
|
assert_equal s, JSON(JSON(s), :create_additions => true)
|
152
150
|
struct = Struct.new :foo, :bar
|
153
151
|
s = struct.new 4711, 'foot'
|
154
|
-
|
152
|
+
assert_raise(JSONError) { JSON(s) }
|
155
153
|
begin
|
156
154
|
raise TypeError, "test me"
|
157
155
|
rescue TypeError => e
|
@@ -167,19 +165,19 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
167
165
|
|
168
166
|
def test_utc_datetime
|
169
167
|
now = Time.now
|
170
|
-
d = DateTime.parse(now.to_s, :create_additions => true)
|
171
|
-
assert_equal d,
|
172
|
-
d = DateTime.parse(now.utc.to_s)
|
173
|
-
assert_equal d,
|
168
|
+
d = DateTime.parse(now.to_s, :create_additions => true) # usual case
|
169
|
+
assert_equal d, parse(d.to_json, :create_additions => true)
|
170
|
+
d = DateTime.parse(now.utc.to_s) # of = 0
|
171
|
+
assert_equal d, parse(d.to_json, :create_additions => true)
|
174
172
|
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
|
175
|
-
assert_equal d,
|
173
|
+
assert_equal d, parse(d.to_json, :create_additions => true)
|
176
174
|
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
|
177
|
-
assert_equal d,
|
175
|
+
assert_equal d, parse(d.to_json, :create_additions => true)
|
178
176
|
end
|
179
177
|
|
180
178
|
def test_rational_complex
|
181
|
-
assert_equal Rational(2, 9),
|
182
|
-
assert_equal Complex(2, 9),
|
179
|
+
assert_equal Rational(2, 9), parse(JSON(Rational(2, 9)), :create_additions => true)
|
180
|
+
assert_equal Complex(2, 9), parse(JSON(Complex(2, 9)), :create_additions => true)
|
183
181
|
end
|
184
182
|
|
185
183
|
def test_bigdecimal
|
@@ -191,6 +189,15 @@ class TestJSONAddition < Test::Unit::TestCase
|
|
191
189
|
o = OpenStruct.new
|
192
190
|
# XXX this won't work; o.foo = { :bar => true }
|
193
191
|
o.foo = { 'bar' => true }
|
194
|
-
assert_equal o,
|
192
|
+
assert_equal o, parse(JSON(o), :create_additions => true)
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_set
|
196
|
+
s = Set.new([:a, :b, :c, :a])
|
197
|
+
assert_equal s, JSON.parse(JSON(s), :create_additions => true)
|
198
|
+
ss = SortedSet.new([:d, :b, :a, :c])
|
199
|
+
ss_again = JSON.parse(JSON(ss), :create_additions => true)
|
200
|
+
assert_kind_of ss.class, ss_again
|
201
|
+
assert_equal ss, ss_again
|
195
202
|
end
|
196
203
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#frozen_string_literal: false
|
2
|
+
require 'test_helper'
|
3
|
+
require 'stringio'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
class JSONCommonInterfaceTest < Test::Unit::TestCase
|
7
|
+
include JSON
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@hash = {
|
11
|
+
'a' => 2,
|
12
|
+
'b' => 3.141,
|
13
|
+
'c' => 'c',
|
14
|
+
'd' => [ 1, "b", 3.14 ],
|
15
|
+
'e' => { 'foo' => 'bar' },
|
16
|
+
'g' => "\"\0\037",
|
17
|
+
'h' => 1000.0,
|
18
|
+
'i' => 0.001
|
19
|
+
}
|
20
|
+
@json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
|
21
|
+
'"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_index
|
25
|
+
assert_equal @json, JSON[@hash]
|
26
|
+
assert_equal @hash, JSON[@json]
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_parser
|
30
|
+
assert_match(/::Parser\z/, JSON.parser.name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_generator
|
34
|
+
assert_match(/::Generator\z/, JSON.generator.name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_state
|
38
|
+
assert_match(/::Generator::State\z/, JSON.state.name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_create_id
|
42
|
+
assert_equal 'json_class', JSON.create_id
|
43
|
+
JSON.create_id = 'foo_bar'
|
44
|
+
assert_equal 'foo_bar', JSON.create_id
|
45
|
+
ensure
|
46
|
+
JSON.create_id = 'json_class'
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_deep_const_get
|
50
|
+
assert_raise(ArgumentError) { JSON.deep_const_get('Nix::Da') }
|
51
|
+
assert_equal File::SEPARATOR, JSON.deep_const_get('File::SEPARATOR')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_parse
|
55
|
+
assert_equal [ 1, 2, 3, ], JSON.parse('[ 1, 2, 3 ]')
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_parse_bang
|
59
|
+
assert_equal [ 1, Infinity, 3, ], JSON.parse!('[ 1, Infinity, 3 ]')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_generate
|
63
|
+
assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_fast_generate
|
67
|
+
assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_pretty_generate
|
71
|
+
assert_equal "[\n 1,\n 2,\n 3\n]", JSON.pretty_generate([ 1, 2, 3 ])
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_load
|
75
|
+
assert_equal @hash, JSON.load(@json)
|
76
|
+
tempfile = Tempfile.open('@json')
|
77
|
+
tempfile.write @json
|
78
|
+
tempfile.rewind
|
79
|
+
assert_equal @hash, JSON.load(tempfile)
|
80
|
+
stringio = StringIO.new(@json)
|
81
|
+
stringio.rewind
|
82
|
+
assert_equal @hash, JSON.load(stringio)
|
83
|
+
assert_equal nil, JSON.load(nil)
|
84
|
+
assert_equal nil, JSON.load('')
|
85
|
+
ensure
|
86
|
+
tempfile.close!
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_load_with_options
|
90
|
+
json = '{ "foo": NaN }'
|
91
|
+
assert JSON.load(json, nil, :allow_nan => true)['foo'].nan?
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_load_null
|
95
|
+
assert_equal nil, JSON.load(nil, nil, :allow_blank => true)
|
96
|
+
assert_raise(TypeError) { JSON.load(nil, nil, :allow_blank => false) }
|
97
|
+
assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_dump
|
101
|
+
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
|
102
|
+
assert_equal too_deep, dump(eval(too_deep))
|
103
|
+
assert_kind_of String, Marshal.dump(eval(too_deep))
|
104
|
+
assert_raise(ArgumentError) { dump(eval(too_deep), 100) }
|
105
|
+
assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
|
106
|
+
assert_equal too_deep, dump(eval(too_deep), 101)
|
107
|
+
assert_kind_of String, Marshal.dump(eval(too_deep), 101)
|
108
|
+
output = StringIO.new
|
109
|
+
dump(eval(too_deep), output)
|
110
|
+
assert_equal too_deep, output.string
|
111
|
+
output = StringIO.new
|
112
|
+
dump(eval(too_deep), output, 101)
|
113
|
+
assert_equal too_deep, output.string
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_dump_should_modify_defaults
|
117
|
+
max_nesting = JSON.dump_default_options[:max_nesting]
|
118
|
+
dump([], StringIO.new, 10)
|
119
|
+
assert_equal max_nesting, JSON.dump_default_options[:max_nesting]
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_JSON
|
123
|
+
assert_equal @json, JSON(@hash)
|
124
|
+
assert_equal @hash, JSON(@json)
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#frozen_string_literal: false
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class JSONEncodingTest < Test::Unit::TestCase
|
6
|
+
include JSON
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@utf_8 = '"© ≠ €!"'
|
10
|
+
@ascii_8bit = @utf_8.dup.force_encoding('ascii-8bit')
|
11
|
+
@parsed = "© ≠ €!"
|
12
|
+
@generated = '"\u00a9 \u2260 \u20ac!"'
|
13
|
+
if String.method_defined?(:encode)
|
14
|
+
@utf_16_data = @parsed.encode('utf-16be', 'utf-8')
|
15
|
+
@utf_16be = @utf_8.encode('utf-16be', 'utf-8')
|
16
|
+
@utf_16le = @utf_8.encode('utf-16le', 'utf-8')
|
17
|
+
@utf_32be = @utf_8.encode('utf-32be', 'utf-8')
|
18
|
+
@utf_32le = @utf_8.encode('utf-32le', 'utf-8')
|
19
|
+
else
|
20
|
+
require 'iconv'
|
21
|
+
@utf_16_data, = Iconv.iconv('utf-16be', 'utf-8', @parsed)
|
22
|
+
@utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
|
23
|
+
@utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
|
24
|
+
@utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
|
25
|
+
@utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_parse
|
30
|
+
assert_equal @parsed, JSON.parse(@ascii_8bit)
|
31
|
+
assert_equal @parsed, JSON.parse(@utf_8)
|
32
|
+
assert_equal @parsed, JSON.parse(@utf_16be)
|
33
|
+
assert_equal @parsed, JSON.parse(@utf_16le)
|
34
|
+
assert_equal @parsed, JSON.parse(@utf_32be)
|
35
|
+
assert_equal @parsed, JSON.parse(@utf_32le)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_generate
|
39
|
+
assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
|
40
|
+
assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_unicode
|
44
|
+
assert_equal '""', ''.to_json
|
45
|
+
assert_equal '"\\b"', "\b".to_json
|
46
|
+
assert_equal '"\u0001"', 0x1.chr.to_json
|
47
|
+
assert_equal '"\u001f"', 0x1f.chr.to_json
|
48
|
+
assert_equal '" "', ' '.to_json
|
49
|
+
assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
|
50
|
+
utf8 = [ "© ≠ €! \01" ]
|
51
|
+
json = '["© ≠ €! \u0001"]'
|
52
|
+
assert_equal json, utf8.to_json(:ascii_only => false)
|
53
|
+
assert_equal utf8, parse(json)
|
54
|
+
json = '["\u00a9 \u2260 \u20ac! \u0001"]'
|
55
|
+
assert_equal json, utf8.to_json(:ascii_only => true)
|
56
|
+
assert_equal utf8, parse(json)
|
57
|
+
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
|
58
|
+
json = "[\"\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212\"]"
|
59
|
+
assert_equal utf8, parse(json)
|
60
|
+
assert_equal json, utf8.to_json(:ascii_only => false)
|
61
|
+
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
|
62
|
+
assert_equal utf8, parse(json)
|
63
|
+
json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
|
64
|
+
assert_equal json, utf8.to_json(:ascii_only => true)
|
65
|
+
assert_equal utf8, parse(json)
|
66
|
+
utf8 = ['საქართველო']
|
67
|
+
json = '["საქართველო"]'
|
68
|
+
assert_equal json, utf8.to_json(:ascii_only => false)
|
69
|
+
json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
|
70
|
+
assert_equal json, utf8.to_json(:ascii_only => true)
|
71
|
+
assert_equal utf8, parse(json)
|
72
|
+
assert_equal '["Ã"]', generate(["Ã"], :ascii_only => false)
|
73
|
+
assert_equal '["\\u00c3"]', generate(["Ã"], :ascii_only => true)
|
74
|
+
assert_equal ["€"], parse('["\u20ac"]')
|
75
|
+
utf8 = ["\xf0\xa0\x80\x81"]
|
76
|
+
json = "[\"\xf0\xa0\x80\x81\"]"
|
77
|
+
assert_equal json, generate(utf8, :ascii_only => false)
|
78
|
+
assert_equal utf8, parse(json)
|
79
|
+
json = '["\ud840\udc01"]'
|
80
|
+
assert_equal json, generate(utf8, :ascii_only => true)
|
81
|
+
assert_equal utf8, parse(json)
|
82
|
+
assert_raise(JSON::ParserError) { parse('"\u"') }
|
83
|
+
assert_raise(JSON::ParserError) { parse('"\ud800"') }
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_chars
|
87
|
+
(0..0x7f).each do |i|
|
88
|
+
json = '["\u%04x"]' % i
|
89
|
+
if RUBY_VERSION >= "1.9."
|
90
|
+
i = i.chr
|
91
|
+
end
|
92
|
+
assert_equal i, parse(json).first[0]
|
93
|
+
if i == ?\b
|
94
|
+
generated = generate(["" << i])
|
95
|
+
assert '["\b"]' == generated || '["\10"]' == generated
|
96
|
+
elsif [?\n, ?\r, ?\t, ?\f].include?(i)
|
97
|
+
assert_equal '[' << ('' << i).dump << ']', generate(["" << i])
|
98
|
+
elsif i.chr < 0x20.chr
|
99
|
+
assert_equal json, generate(["" << i])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
assert_raise(JSON::GeneratorError) do
|
103
|
+
generate(["\x80"], :ascii_only => true)
|
104
|
+
end
|
105
|
+
assert_equal "\302\200", parse('["\u0080"]').first
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#frozen_string_literal: false
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class JSONExtParserTest < Test::Unit::TestCase
|
5
|
+
if defined?(JSON::Ext::Parser)
|
6
|
+
def test_allocate
|
7
|
+
parser = JSON::Ext::Parser.new("{}")
|
8
|
+
assert_raise(TypeError, '[ruby-core:35079]') do
|
9
|
+
parser.__send__(:initialize, "{}")
|
10
|
+
end
|
11
|
+
parser = JSON::Ext::Parser.allocate
|
12
|
+
assert_raise(TypeError, '[ruby-core:35079]') { parser.source }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,12 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#frozen_string_literal: false
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
|
5
|
-
require File.join(File.dirname(__FILE__), 'setup_variant')
|
6
|
-
|
7
|
-
class TestJSONFixtures < Test::Unit::TestCase
|
4
|
+
class JSONFixturesTest < Test::Unit::TestCase
|
8
5
|
def setup
|
9
|
-
fixtures = File.join(File.dirname(__FILE__), 'fixtures
|
6
|
+
fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
|
10
7
|
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
|
11
8
|
@passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
12
9
|
@failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
@@ -26,10 +23,15 @@ class TestJSONFixtures < Test::Unit::TestCase
|
|
26
23
|
|
27
24
|
def test_failing
|
28
25
|
for name, source in @failed
|
29
|
-
|
26
|
+
assert_raise(JSON::ParserError, JSON::NestingError,
|
30
27
|
"Did not fail for fixture '#{name}': #{source.inspect}") do
|
31
28
|
JSON.parse(source)
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
32
|
+
|
33
|
+
def test_sanity
|
34
|
+
assert(@passed.size > 5)
|
35
|
+
assert(@failed.size > 20)
|
36
|
+
end
|
35
37
|
end
|
@@ -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,63 @@ 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
|
+
return if RUBY_ENGINE == 'jruby'
|
53
|
+
stress = GC.stress
|
54
|
+
const = JSON::SAFE_STATE_PROTOTYPE.dup
|
55
|
+
|
56
|
+
bignum_too_long_to_embed_as_string = 1234567890123456789012345
|
57
|
+
expect = bignum_too_long_to_embed_as_string.to_s
|
58
|
+
GC.stress = true
|
59
|
+
|
60
|
+
10.times do |i|
|
61
|
+
tmp = bignum_too_long_to_embed_as_string.to_json
|
62
|
+
raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
|
63
|
+
end
|
64
|
+
|
65
|
+
silence do
|
66
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, nil
|
67
|
+
end
|
68
|
+
|
69
|
+
10.times do |i|
|
70
|
+
assert_raise TypeError do
|
71
|
+
bignum_too_long_to_embed_as_string.to_json
|
72
|
+
end
|
73
|
+
end
|
74
|
+
ensure
|
75
|
+
GC.stress = stress
|
76
|
+
silence do
|
77
|
+
JSON.const_set :SAFE_STATE_PROTOTYPE, const
|
78
|
+
end
|
79
|
+
end if JSON.const_defined?("Ext")
|
80
|
+
|
43
81
|
def test_generate
|
44
82
|
json = generate(@hash)
|
45
|
-
assert_equal(
|
83
|
+
assert_equal(parse(@json2), parse(json))
|
46
84
|
json = JSON[@hash]
|
47
|
-
assert_equal(
|
85
|
+
assert_equal(parse(@json2), parse(json))
|
48
86
|
parsed_json = parse(json)
|
49
87
|
assert_equal(@hash, parsed_json)
|
50
88
|
json = generate({1=>2})
|
51
89
|
assert_equal('{"1":2}', json)
|
52
90
|
parsed_json = parse(json)
|
53
91
|
assert_equal({"1"=>2}, parsed_json)
|
54
|
-
|
55
|
-
assert_equal '666', generate(666, :quirks_mode => true)
|
92
|
+
assert_equal '666', generate(666)
|
56
93
|
end
|
57
94
|
|
58
95
|
def test_generate_pretty
|
59
96
|
json = pretty_generate(@hash)
|
60
|
-
# hashes aren't (insertion) ordered on every ruby implementation
|
61
|
-
assert_equal(
|
97
|
+
# hashes aren't (insertion) ordered on every ruby implementation
|
98
|
+
# assert_equal(@json3, json)
|
99
|
+
assert_equal(parse(@json3), parse(json))
|
62
100
|
parsed_json = parse(json)
|
63
101
|
assert_equal(@hash, parsed_json)
|
64
102
|
json = pretty_generate({1=>2})
|
@@ -69,8 +107,7 @@ EOT
|
|
69
107
|
EOT
|
70
108
|
parsed_json = parse(json)
|
71
109
|
assert_equal({"1"=>2}, parsed_json)
|
72
|
-
|
73
|
-
assert_equal '666', pretty_generate(666, :quirks_mode => true)
|
110
|
+
assert_equal '666', pretty_generate(666)
|
74
111
|
end
|
75
112
|
|
76
113
|
def test_generate_custom
|
@@ -88,30 +125,26 @@ EOT
|
|
88
125
|
|
89
126
|
def test_fast_generate
|
90
127
|
json = fast_generate(@hash)
|
91
|
-
assert_equal(
|
128
|
+
assert_equal(parse(@json2), parse(json))
|
92
129
|
parsed_json = parse(json)
|
93
130
|
assert_equal(@hash, parsed_json)
|
94
131
|
json = fast_generate({1=>2})
|
95
132
|
assert_equal('{"1":2}', json)
|
96
133
|
parsed_json = parse(json)
|
97
134
|
assert_equal({"1"=>2}, parsed_json)
|
98
|
-
|
99
|
-
assert_equal '666', fast_generate(666, :quirks_mode => true)
|
135
|
+
assert_equal '666', fast_generate(666)
|
100
136
|
end
|
101
137
|
|
102
138
|
def test_own_state
|
103
139
|
state = State.new
|
104
140
|
json = generate(@hash, state)
|
105
|
-
assert_equal(
|
141
|
+
assert_equal(parse(@json2), parse(json))
|
106
142
|
parsed_json = parse(json)
|
107
143
|
assert_equal(@hash, parsed_json)
|
108
144
|
json = generate({1=>2}, state)
|
109
145
|
assert_equal('{"1":2}', json)
|
110
146
|
parsed_json = parse(json)
|
111
147
|
assert_equal({"1"=>2}, parsed_json)
|
112
|
-
assert_raise(GeneratorError) { generate(666, state) }
|
113
|
-
state.quirks_mode = true
|
114
|
-
assert state.quirks_mode?
|
115
148
|
assert_equal '666', generate(666, state)
|
116
149
|
end
|
117
150
|
|
@@ -123,12 +156,12 @@ EOT
|
|
123
156
|
assert s[:check_circular?]
|
124
157
|
h = { 1=>2 }
|
125
158
|
h[3] = h
|
126
|
-
|
127
|
-
|
159
|
+
assert_raise(JSON::NestingError) { generate(h) }
|
160
|
+
assert_raise(JSON::NestingError) { generate(h, s) }
|
128
161
|
s = JSON.state.new
|
129
162
|
a = [ 1, 2 ]
|
130
163
|
a << a
|
131
|
-
|
164
|
+
assert_raise(JSON::NestingError) { generate(a, s) }
|
132
165
|
assert s.check_circular?
|
133
166
|
assert s[:check_circular?]
|
134
167
|
end
|
@@ -140,7 +173,6 @@ EOT
|
|
140
173
|
:array_nl => "\n",
|
141
174
|
:ascii_only => false,
|
142
175
|
:buffer_initial_length => 1024,
|
143
|
-
:quirks_mode => false,
|
144
176
|
:depth => 0,
|
145
177
|
:indent => " ",
|
146
178
|
:max_nesting => 100,
|
@@ -157,7 +189,6 @@ EOT
|
|
157
189
|
:array_nl => "",
|
158
190
|
:ascii_only => false,
|
159
191
|
:buffer_initial_length => 1024,
|
160
|
-
:quirks_mode => false,
|
161
192
|
:depth => 0,
|
162
193
|
:indent => "",
|
163
194
|
:max_nesting => 100,
|
@@ -174,7 +205,6 @@ EOT
|
|
174
205
|
:array_nl => "",
|
175
206
|
:ascii_only => false,
|
176
207
|
:buffer_initial_length => 1024,
|
177
|
-
:quirks_mode => false,
|
178
208
|
:depth => 0,
|
179
209
|
:indent => "",
|
180
210
|
:max_nesting => 0,
|
@@ -185,34 +215,34 @@ EOT
|
|
185
215
|
end
|
186
216
|
|
187
217
|
def test_allow_nan
|
188
|
-
|
218
|
+
assert_raise(GeneratorError) { generate([JSON::NaN]) }
|
189
219
|
assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
|
190
|
-
|
191
|
-
|
220
|
+
assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
|
221
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
|
192
222
|
assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
|
193
|
-
|
223
|
+
assert_raise(GeneratorError) { generate([JSON::Infinity]) }
|
194
224
|
assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
|
195
|
-
|
196
|
-
|
225
|
+
assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
|
226
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
|
197
227
|
assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
|
198
|
-
|
228
|
+
assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
|
199
229
|
assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
|
200
|
-
|
201
|
-
|
230
|
+
assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
|
231
|
+
assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
|
202
232
|
assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
|
203
233
|
end
|
204
234
|
|
205
235
|
def test_depth
|
206
236
|
ary = []; ary << ary
|
207
237
|
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
208
|
-
|
238
|
+
assert_raise(JSON::NestingError) { generate(ary) }
|
209
239
|
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
|
210
240
|
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
211
|
-
|
241
|
+
assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
|
212
242
|
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
|
213
243
|
s = JSON.state.new
|
214
244
|
assert_equal 0, s.depth
|
215
|
-
|
245
|
+
assert_raise(JSON::NestingError) { ary.to_json(s) }
|
216
246
|
assert_equal 100, s.depth
|
217
247
|
end
|
218
248
|
|
@@ -285,12 +315,13 @@ EOT
|
|
285
315
|
if defined?(JSON::Ext::Generator)
|
286
316
|
def test_broken_bignum # [ruby-core:38867]
|
287
317
|
pid = fork do
|
288
|
-
|
318
|
+
x = 1 << 64
|
319
|
+
x.class.class_eval do
|
289
320
|
def to_s
|
290
321
|
end
|
291
322
|
end
|
292
323
|
begin
|
293
|
-
JSON::Ext::Generator::State.new.generate(
|
324
|
+
JSON::Ext::Generator::State.new.generate(x)
|
294
325
|
exit 1
|
295
326
|
rescue TypeError
|
296
327
|
exit 0
|
@@ -331,7 +362,60 @@ EOT
|
|
331
362
|
|
332
363
|
def test_json_generate
|
333
364
|
assert_raise JSON::GeneratorError do
|
334
|
-
assert_equal true,
|
365
|
+
assert_equal true, generate(["\xea"])
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_nesting
|
370
|
+
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
|
371
|
+
too_deep_ary = eval too_deep
|
372
|
+
assert_raise(JSON::NestingError) { generate too_deep_ary }
|
373
|
+
assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
|
374
|
+
ok = generate too_deep_ary, :max_nesting => 101
|
375
|
+
assert_equal too_deep, ok
|
376
|
+
ok = generate too_deep_ary, :max_nesting => nil
|
377
|
+
assert_equal too_deep, ok
|
378
|
+
ok = generate too_deep_ary, :max_nesting => false
|
379
|
+
assert_equal too_deep, ok
|
380
|
+
ok = generate too_deep_ary, :max_nesting => 0
|
381
|
+
assert_equal too_deep, ok
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_backslash
|
385
|
+
data = [ '\\.(?i:gif|jpe?g|png)$' ]
|
386
|
+
json = '["\\\\.(?i:gif|jpe?g|png)$"]'
|
387
|
+
assert_equal json, generate(data)
|
388
|
+
#
|
389
|
+
data = [ '\\"' ]
|
390
|
+
json = '["\\\\\""]'
|
391
|
+
assert_equal json, generate(data)
|
392
|
+
#
|
393
|
+
data = [ '/' ]
|
394
|
+
json = '["/"]'
|
395
|
+
assert_equal json, generate(data)
|
396
|
+
#
|
397
|
+
data = ['"']
|
398
|
+
json = '["\""]'
|
399
|
+
assert_equal json, generate(data)
|
400
|
+
#
|
401
|
+
data = ["'"]
|
402
|
+
json = '["\\\'"]'
|
403
|
+
assert_equal '["\'"]', generate(data)
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_string_subclass
|
407
|
+
s = Class.new(String) do
|
408
|
+
def to_s; self; end
|
409
|
+
undef to_json
|
410
|
+
end
|
411
|
+
assert_nothing_raised(SystemStackError) do
|
412
|
+
assert_equal '["foo"]', JSON.generate([s.new('foo')])
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
if defined?(Encoding)
|
417
|
+
def test_nonutf8_encoding
|
418
|
+
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
|
335
419
|
end
|
336
420
|
end
|
337
421
|
end
|