json 1.8.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +5 -3
  4. data/CHANGES +5 -5
  5. data/Gemfile +3 -1
  6. data/README.md +131 -84
  7. data/Rakefile +17 -10
  8. data/VERSION +1 -1
  9. data/ext/json/ext/generator/generator.c +1 -52
  10. data/ext/json/ext/generator/generator.h +0 -5
  11. data/ext/json/ext/parser/extconf.rb +3 -0
  12. data/ext/json/ext/parser/parser.c +304 -458
  13. data/ext/json/ext/parser/parser.h +0 -1
  14. data/ext/json/ext/parser/parser.rl +35 -152
  15. data/ext/json/extconf.rb +0 -1
  16. data/java/src/json/ext/Generator.java +2 -5
  17. data/java/src/json/ext/GeneratorState.java +2 -54
  18. data/java/src/json/ext/OptionsReader.java +1 -1
  19. data/java/src/json/ext/Parser.java +109 -409
  20. data/java/src/json/ext/Parser.rl +24 -117
  21. data/java/src/json/ext/RuntimeInfo.java +0 -4
  22. data/json.gemspec +0 -0
  23. data/json_pure.gemspec +7 -7
  24. data/lib/json.rb +1 -0
  25. data/lib/json/add/bigdecimal.rb +1 -0
  26. data/lib/json/add/complex.rb +2 -1
  27. data/lib/json/add/core.rb +1 -0
  28. data/lib/json/add/date.rb +1 -1
  29. data/lib/json/add/date_time.rb +1 -1
  30. data/lib/json/add/exception.rb +1 -1
  31. data/lib/json/add/ostruct.rb +1 -1
  32. data/lib/json/add/range.rb +1 -1
  33. data/lib/json/add/rational.rb +1 -0
  34. data/lib/json/add/regexp.rb +1 -1
  35. data/lib/json/add/struct.rb +1 -1
  36. data/lib/json/add/symbol.rb +1 -1
  37. data/lib/json/add/time.rb +1 -1
  38. data/lib/json/common.rb +24 -52
  39. data/lib/json/ext.rb +0 -6
  40. data/lib/json/generic_object.rb +5 -4
  41. data/lib/json/pure.rb +2 -8
  42. data/lib/json/pure/generator.rb +51 -123
  43. data/lib/json/pure/parser.rb +28 -80
  44. data/lib/json/version.rb +2 -1
  45. data/references/rfc7159.txt +899 -0
  46. data/tests/fixtures/obsolete_fail1.json +1 -0
  47. data/tests/{test_json_addition.rb → json_addition_test.rb} +22 -25
  48. data/tests/json_common_interface_test.rb +126 -0
  49. data/tests/json_encoding_test.rb +105 -0
  50. data/tests/json_ext_parser_test.rb +15 -0
  51. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
  52. data/tests/{test_json_generate.rb → json_generator_test.rb} +65 -37
  53. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  54. data/tests/json_parser_test.rb +448 -0
  55. data/tests/json_string_matching_test.rb +38 -0
  56. data/tests/test_helper.rb +23 -0
  57. data/tools/fuzz.rb +1 -9
  58. metadata +19 -32
  59. data/TODO +0 -1
  60. data/tests/fixtures/fail1.json +0 -1
  61. data/tests/setup_variant.rb +0 -11
  62. data/tests/test_json.rb +0 -519
  63. data/tests/test_json_encoding.rb +0 -65
  64. data/tests/test_json_string_matching.rb +0 -39
  65. data/tests/test_json_unicode.rb +0 -72
@@ -1,9 +1,7 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
3
 
4
- require 'test/unit'
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, JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
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 = JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
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, l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
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)
@@ -0,0 +1,448 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'tempfile'
6
+ require 'ostruct'
7
+
8
+ class JSONParserTest < Test::Unit::TestCase
9
+ include JSON
10
+
11
+ def test_construction
12
+ parser = JSON::Parser.new('test')
13
+ assert_equal 'test', parser.source
14
+ end
15
+
16
+ def test_argument_encoding
17
+ source = "{}".encode("UTF-16")
18
+ JSON::Parser.new(source)
19
+ assert_equal Encoding::UTF_16, source.encoding
20
+ end if defined?(Encoding::UTF_16)
21
+
22
+ def test_error_message_encoding
23
+ bug10705 = '[ruby-core:67386] [Bug #10705]'
24
+ json = ".\"\xE2\x88\x9A\"".force_encoding(Encoding::UTF_8)
25
+ e = assert_raise(JSON::ParserError) {
26
+ JSON::Ext::Parser.new(json).parse
27
+ }
28
+ assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
29
+ assert_include(e.message, json, bug10705)
30
+ end if defined?(Encoding::UTF_8) and defined?(JSON::Ext::Parser)
31
+
32
+ def test_parsing
33
+ parser = JSON::Parser.new('"test"')
34
+ assert_equal 'test', parser.parse
35
+ end
36
+
37
+ def test_parser_reset
38
+ parser = Parser.new('{"a":"b"}')
39
+ assert_equal({ 'a' => 'b' }, parser.parse)
40
+ assert_equal({ 'a' => 'b' }, parser.parse)
41
+ end
42
+
43
+ def test_parse_simple_arrays
44
+ assert_equal([], parse('[]'))
45
+ assert_equal([], parse(' [ ] '))
46
+ assert_equal([ nil ], parse('[null]'))
47
+ assert_equal([ false ], parse('[false]'))
48
+ assert_equal([ true ], parse('[true]'))
49
+ assert_equal([ -23 ], parse('[-23]'))
50
+ assert_equal([ 23 ], parse('[23]'))
51
+ assert_equal_float([ 0.23 ], parse('[0.23]'))
52
+ assert_equal_float([ 0.0 ], parse('[0e0]'))
53
+ assert_equal([""], parse('[""]'))
54
+ assert_equal(["foobar"], parse('["foobar"]'))
55
+ assert_equal([{}], parse('[{}]'))
56
+ end
57
+
58
+ def test_parse_simple_objects
59
+ assert_equal({}, parse('{}'))
60
+ assert_equal({}, parse(' { } '))
61
+ assert_equal({ "a" => nil }, parse('{ "a" : null}'))
62
+ assert_equal({ "a" => nil }, parse('{"a":null}'))
63
+ assert_equal({ "a" => false }, parse('{ "a" : false } '))
64
+ assert_equal({ "a" => false }, parse('{"a":false}'))
65
+ assert_raise(JSON::ParserError) { parse('{false}') }
66
+ assert_equal({ "a" => true }, parse('{"a":true}'))
67
+ assert_equal({ "a" => true }, parse(' { "a" : true } '))
68
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
69
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
70
+ assert_equal({ "a" => 23 }, parse('{"a":23 } '))
71
+ assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
72
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
73
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
74
+ end
75
+
76
+ def test_parse_numbers
77
+ assert_raise(JSON::ParserError) { parse('+23.2') }
78
+ assert_raise(JSON::ParserError) { parse('+23') }
79
+ assert_raise(JSON::ParserError) { parse('.23') }
80
+ assert_raise(JSON::ParserError) { parse('023') }
81
+ assert_equal 23, parse('23')
82
+ assert_equal -23, parse('-23')
83
+ assert_equal_float 3.141, parse('3.141')
84
+ assert_equal_float -3.141, parse('-3.141')
85
+ assert_equal_float 3.141, parse('3141e-3')
86
+ assert_equal_float 3.141, parse('3141.1e-3')
87
+ assert_equal_float 3.141, parse('3141E-3')
88
+ assert_equal_float 3.141, parse('3141.0E-3')
89
+ assert_equal_float -3.141, parse('-3141.0e-3')
90
+ assert_equal_float -3.141, parse('-3141e-3')
91
+ assert_raise(ParserError) { parse('NaN') }
92
+ assert parse('NaN', :allow_nan => true).nan?
93
+ assert_raise(ParserError) { parse('Infinity') }
94
+ assert_equal 1.0/0, parse('Infinity', :allow_nan => true)
95
+ assert_raise(ParserError) { parse('-Infinity') }
96
+ assert_equal -1.0/0, parse('-Infinity', :allow_nan => true)
97
+ end
98
+
99
+ if Array.method_defined?(:permutation)
100
+ def test_parse_more_complex_arrays
101
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
102
+ a.permutation.each do |perm|
103
+ json = pretty_generate(perm)
104
+ assert_equal perm, parse(json)
105
+ end
106
+ end
107
+
108
+ def test_parse_complex_objects
109
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
110
+ a.permutation.each do |perm|
111
+ s = "a"
112
+ orig_obj = perm.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
113
+ json = pretty_generate(orig_obj)
114
+ assert_equal orig_obj, parse(json)
115
+ end
116
+ end
117
+ end
118
+
119
+ def test_parse_arrays
120
+ assert_equal([1,2,3], parse('[1,2,3]'))
121
+ assert_equal([1.2,2,3], parse('[1.2,2,3]'))
122
+ assert_equal([[],[[],[]]], parse('[[],[[],[]]]'))
123
+ assert_equal([], parse('[]'))
124
+ assert_equal([], parse(' [ ] '))
125
+ assert_equal([1], parse('[1]'))
126
+ assert_equal([1], parse(' [ 1 ] '))
127
+ ary = [[1], ["foo"], [3.14], [4711.0], [2.718], [nil],
128
+ [[1, -2, 3]], [false], [true]]
129
+ assert_equal(ary,
130
+ parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]],[false],[true]]'))
131
+ assert_equal(ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]\s
132
+ , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
133
+ end
134
+
135
+ def test_parse_json_primitive_values
136
+ assert_raise(JSON::ParserError) { parse('') }
137
+ assert_raise(TypeError) { parse(nil) }
138
+ assert_raise(JSON::ParserError) { parse(' /* foo */ ') }
139
+ assert_equal nil, parse('null')
140
+ assert_equal false, parse('false')
141
+ assert_equal true, parse('true')
142
+ assert_equal 23, parse('23')
143
+ assert_equal 1, parse('1')
144
+ assert_equal_float 3.141, parse('3.141'), 1E-3
145
+ assert_equal 2 ** 64, parse('18446744073709551616')
146
+ assert_equal 'foo', parse('"foo"')
147
+ assert parse('NaN', :allow_nan => true).nan?
148
+ assert parse('Infinity', :allow_nan => true).infinite?
149
+ assert parse('-Infinity', :allow_nan => true).infinite?
150
+ assert_raise(JSON::ParserError) { parse('[ 1, ]') }
151
+ end
152
+
153
+ def test_parse_some_strings
154
+ assert_equal([""], parse('[""]'))
155
+ assert_equal(["\\"], parse('["\\\\"]'))
156
+ assert_equal(['"'], parse('["\""]'))
157
+ assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
158
+ assert_equal(
159
+ ["\"\b\n\r\t\0\037"],
160
+ parse('["\"\b\n\r\t\u0000\u001f"]')
161
+ )
162
+ end
163
+
164
+ def test_parse_big_integers
165
+ json1 = JSON(orig = (1 << 31) - 1)
166
+ assert_equal orig, parse(json1)
167
+ json2 = JSON(orig = 1 << 31)
168
+ assert_equal orig, parse(json2)
169
+ json3 = JSON(orig = (1 << 62) - 1)
170
+ assert_equal orig, parse(json3)
171
+ json4 = JSON(orig = 1 << 62)
172
+ assert_equal orig, parse(json4)
173
+ json5 = JSON(orig = 1 << 64)
174
+ assert_equal orig, parse(json5)
175
+ end
176
+
177
+ def test_some_wrong_inputs
178
+ assert_raise(ParserError) { parse('[] bla') }
179
+ assert_raise(ParserError) { parse('[] 1') }
180
+ assert_raise(ParserError) { parse('[] []') }
181
+ assert_raise(ParserError) { parse('[] {}') }
182
+ assert_raise(ParserError) { parse('{} []') }
183
+ assert_raise(ParserError) { parse('{} {}') }
184
+ assert_raise(ParserError) { parse('[NULL]') }
185
+ assert_raise(ParserError) { parse('[FALSE]') }
186
+ assert_raise(ParserError) { parse('[TRUE]') }
187
+ assert_raise(ParserError) { parse('[07] ') }
188
+ assert_raise(ParserError) { parse('[0a]') }
189
+ assert_raise(ParserError) { parse('[1.]') }
190
+ assert_raise(ParserError) { parse(' ') }
191
+ end
192
+
193
+ def test_symbolize_names
194
+ assert_equal({ "foo" => "bar", "baz" => "quux" },
195
+ parse('{"foo":"bar", "baz":"quux"}'))
196
+ assert_equal({ :foo => "bar", :baz => "quux" },
197
+ parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
198
+ assert_raise(ArgumentError) do
199
+ parse('{}', :symbolize_names => true, :create_additions => true)
200
+ end
201
+ end
202
+
203
+ def test_parse_comments
204
+ json = <<EOT
205
+ {
206
+ "key1":"value1", // eol comment
207
+ "key2":"value2" /* multi line
208
+ * comment */,
209
+ "key3":"value3" /* multi line
210
+ // nested eol comment
211
+ * comment */
212
+ }
213
+ EOT
214
+ assert_equal(
215
+ { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
216
+ parse(json))
217
+ json = <<EOT
218
+ {
219
+ "key1":"value1" /* multi line
220
+ // nested eol comment
221
+ /* illegal nested multi line comment */
222
+ * comment */
223
+ }
224
+ EOT
225
+ assert_raise(ParserError) { parse(json) }
226
+ json = <<EOT
227
+ {
228
+ "key1":"value1" /* multi line
229
+ // nested eol comment
230
+ closed multi comment */
231
+ and again, throw an Error */
232
+ }
233
+ EOT
234
+ assert_raise(ParserError) { parse(json) }
235
+ json = <<EOT
236
+ {
237
+ "key1":"value1" /*/*/
238
+ }
239
+ EOT
240
+ assert_equal({ "key1" => "value1" }, parse(json))
241
+ end
242
+
243
+ def test_nesting
244
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
245
+ too_deep_ary = eval too_deep
246
+ assert_raise(JSON::NestingError) { parse too_deep }
247
+ assert_raise(JSON::NestingError) { parse too_deep, :max_nesting => 100 }
248
+ ok = parse too_deep, :max_nesting => 101
249
+ assert_equal too_deep_ary, ok
250
+ ok = parse too_deep, :max_nesting => nil
251
+ assert_equal too_deep_ary, ok
252
+ ok = parse too_deep, :max_nesting => false
253
+ assert_equal too_deep_ary, ok
254
+ ok = parse too_deep, :max_nesting => 0
255
+ assert_equal too_deep_ary, ok
256
+ end
257
+
258
+ def test_backslash
259
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
260
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
261
+ assert_equal data, parse(json)
262
+ #
263
+ data = [ '\\"' ]
264
+ json = '["\\\\\""]'
265
+ assert_equal data, parse(json)
266
+ #
267
+ json = '["/"]'
268
+ data = [ '/' ]
269
+ assert_equal data, parse(json)
270
+ #
271
+ json = '["\""]'
272
+ data = ['"']
273
+ assert_equal data, parse(json)
274
+ #
275
+ json = '["\\\'"]'
276
+ data = ["'"]
277
+ assert_equal data, parse(json)
278
+ end
279
+
280
+
281
+ class SubArray < Array
282
+ def <<(v)
283
+ @shifted = true
284
+ super
285
+ end
286
+
287
+ def shifted?
288
+ @shifted
289
+ end
290
+ end
291
+
292
+ class SubArray2 < Array
293
+ def to_json(*a)
294
+ {
295
+ JSON.create_id => self.class.name,
296
+ 'ary' => to_a,
297
+ }.to_json(*a)
298
+ end
299
+
300
+ def self.json_create(o)
301
+ o.delete JSON.create_id
302
+ o['ary']
303
+ end
304
+ end
305
+
306
+ class SubArrayWrapper
307
+ def initialize
308
+ @data = []
309
+ end
310
+
311
+ attr_reader :data
312
+
313
+ def [](index)
314
+ @data[index]
315
+ end
316
+
317
+ def <<(value)
318
+ @data << value
319
+ @shifted = true
320
+ end
321
+
322
+ def shifted?
323
+ @shifted
324
+ end
325
+ end
326
+
327
+ def test_parse_array_custom_array_derived_class
328
+ res = parse('[1,2]', :array_class => SubArray)
329
+ assert_equal([1,2], res)
330
+ assert_equal(SubArray, res.class)
331
+ assert res.shifted?
332
+ end
333
+
334
+ def test_parse_array_custom_non_array_derived_class
335
+ res = parse('[1,2]', :array_class => SubArrayWrapper)
336
+ assert_equal([1,2], res.data)
337
+ assert_equal(SubArrayWrapper, res.class)
338
+ assert res.shifted?
339
+ end
340
+
341
+ def test_parse_object
342
+ assert_equal({}, parse('{}'))
343
+ assert_equal({}, parse(' { } '))
344
+ assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}'))
345
+ assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } '))
346
+ end
347
+
348
+ class SubHash < Hash
349
+ def []=(k, v)
350
+ @item_set = true
351
+ super
352
+ end
353
+
354
+ def item_set?
355
+ @item_set
356
+ end
357
+ end
358
+
359
+ class SubHash2 < Hash
360
+ def to_json(*a)
361
+ {
362
+ JSON.create_id => self.class.name,
363
+ }.merge(self).to_json(*a)
364
+ end
365
+
366
+ def self.json_create(o)
367
+ o.delete JSON.create_id
368
+ self[o]
369
+ end
370
+ end
371
+
372
+ class SubOpenStruct < OpenStruct
373
+ def [](k)
374
+ __send__(k)
375
+ end
376
+
377
+ def []=(k, v)
378
+ @item_set = true
379
+ __send__("#{k}=", v)
380
+ end
381
+
382
+ def item_set?
383
+ @item_set
384
+ end
385
+ end
386
+
387
+ def test_parse_object_custom_hash_derived_class
388
+ res = parse('{"foo":"bar"}', :object_class => SubHash)
389
+ assert_equal({"foo" => "bar"}, res)
390
+ assert_equal(SubHash, res.class)
391
+ assert res.item_set?
392
+ end
393
+
394
+ def test_parse_object_custom_non_hash_derived_class
395
+ res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
396
+ assert_equal "bar", res.foo
397
+ assert_equal(SubOpenStruct, res.class)
398
+ assert res.item_set?
399
+ end
400
+
401
+ def test_parse_generic_object
402
+ res = parse(
403
+ '{"foo":"bar", "baz":{}}',
404
+ :object_class => JSON::GenericObject
405
+ )
406
+ assert_equal(JSON::GenericObject, res.class)
407
+ assert_equal "bar", res.foo
408
+ assert_equal "bar", res["foo"]
409
+ assert_equal "bar", res[:foo]
410
+ assert_equal "bar", res.to_hash[:foo]
411
+ assert_equal(JSON::GenericObject, res.baz.class)
412
+ end
413
+
414
+ def test_generate_core_subclasses_with_new_to_json
415
+ obj = SubHash2["foo" => SubHash2["bar" => true]]
416
+ obj_json = JSON(obj)
417
+ obj_again = parse(obj_json, :create_additions => true)
418
+ assert_kind_of SubHash2, obj_again
419
+ assert_kind_of SubHash2, obj_again['foo']
420
+ assert obj_again['foo']['bar']
421
+ assert_equal obj, obj_again
422
+ assert_equal ["foo"],
423
+ JSON(JSON(SubArray2["foo"]), :create_additions => true)
424
+ end
425
+
426
+ def test_generate_core_subclasses_with_default_to_json
427
+ assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"])
428
+ assert_equal '["foo"]', JSON(SubArray["foo"])
429
+ end
430
+
431
+ def test_generate_of_core_subclasses
432
+ obj = SubHash["foo" => SubHash["bar" => true]]
433
+ obj_json = JSON(obj)
434
+ obj_again = JSON(obj_json)
435
+ assert_kind_of Hash, obj_again
436
+ assert_kind_of Hash, obj_again['foo']
437
+ assert obj_again['foo']['bar']
438
+ assert_equal obj, obj_again
439
+ end
440
+
441
+ private
442
+
443
+ def assert_equal_float(expected, actual, delta = 1e-2)
444
+ Array === expected and expected = expected.first
445
+ Array === actual and actual = actual.first
446
+ assert_in_delta(expected, actual, delta)
447
+ end
448
+ end