json_pure 1.8.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 +18 -31
  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