oj 2.18.3 → 3.13.14
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/CHANGELOG.md +1324 -0
- data/README.md +51 -204
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +49 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -68
- data/ext/oj/circarray.h +16 -42
- data/ext/oj/code.c +221 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +231 -107
- data/ext/oj/custom.c +1125 -0
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +935 -2513
- data/ext/oj/dump.h +108 -0
- data/ext/oj/dump_compat.c +936 -0
- data/ext/oj/dump_leaf.c +164 -0
- data/ext/oj/dump_object.c +761 -0
- data/ext/oj/dump_strict.c +410 -0
- data/ext/oj/encode.h +7 -42
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -54
- data/ext/oj/err.h +52 -46
- data/ext/oj/extconf.rb +21 -30
- data/ext/oj/fast.c +1097 -1080
- data/ext/oj/intern.c +301 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +893 -0
- data/ext/oj/object.c +549 -620
- data/ext/oj/odd.c +155 -167
- data/ext/oj/odd.h +37 -63
- data/ext/oj/oj.c +1661 -2063
- data/ext/oj/oj.h +341 -270
- data/ext/oj/parse.c +974 -737
- data/ext/oj/parse.h +105 -97
- data/ext/oj/parser.c +1526 -0
- data/ext/oj/parser.h +90 -0
- data/ext/oj/rails.c +1504 -0
- data/ext/oj/rails.h +18 -0
- data/ext/oj/reader.c +141 -163
- data/ext/oj/reader.h +75 -113
- data/ext/oj/resolve.c +45 -93
- data/ext/oj/resolve.h +7 -34
- data/ext/oj/rxclass.c +143 -0
- data/ext/oj/rxclass.h +26 -0
- data/ext/oj/saj.c +447 -511
- data/ext/oj/saj2.c +348 -0
- data/ext/oj/scp.c +91 -138
- data/ext/oj/sparse.c +793 -644
- data/ext/oj/stream_writer.c +331 -0
- data/ext/oj/strict.c +145 -109
- data/ext/oj/string_writer.c +493 -0
- data/ext/oj/trace.c +72 -0
- data/ext/oj/trace.h +28 -0
- data/ext/oj/usual.c +1254 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +62 -70
- data/ext/oj/val_stack.h +95 -129
- data/ext/oj/validate.c +51 -0
- data/ext/oj/wab.c +622 -0
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +17 -8
- data/lib/oj/error.rb +10 -11
- data/lib/oj/json.rb +176 -0
- data/lib/oj/mimic.rb +158 -19
- data/lib/oj/state.rb +132 -0
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +1 -31
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +94 -0
- data/pages/Modes.md +161 -0
- data/pages/Options.md +327 -0
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +167 -0
- data/pages/Security.md +20 -0
- data/pages/WAB.md +13 -0
- data/test/activerecord/result_test.rb +32 -0
- data/test/activesupport4/decoding_test.rb +108 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +133 -0
- data/test/activesupport5/encoding_test.rb +500 -0
- data/test/activesupport5/encoding_test_cases.rb +98 -0
- data/test/activesupport5/test_helper.rb +72 -0
- data/test/activesupport5/time_zone_test_helpers.rb +39 -0
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +9 -0
- data/test/baz.rb +16 -0
- data/test/bug.rb +11 -46
- data/test/foo.rb +69 -16
- data/test/helper.rb +10 -1
- data/test/isolated/shared.rb +12 -8
- data/test/isolated/test_mimic_rails_after.rb +3 -3
- data/test/isolated/test_mimic_rails_before.rb +3 -3
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +153 -0
- data/test/json_gem/json_encoding_test.rb +107 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +397 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +26 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_compat.rb +30 -28
- data/test/perf_dump.rb +50 -0
- data/test/perf_object.rb +1 -1
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +30 -19
- data/test/perf_wab.rb +131 -0
- data/test/prec.rb +23 -0
- data/test/sample.rb +0 -1
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +219 -102
- data/test/test_custom.rb +533 -0
- data/test/test_fast.rb +107 -35
- data/test/test_file.rb +19 -25
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +72 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +357 -70
- data/test/test_parser.rb +27 -0
- data/test/test_parser_saj.rb +245 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +39 -2
- data/test/test_strict.rb +186 -7
- data/test/test_various.rb +160 -774
- data/test/test_wab.rb +307 -0
- data/test/test_writer.rb +90 -2
- data/test/tests.rb +24 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- data/test/zoo.rb +13 -0
- metadata +194 -56
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
- data/test/activesupport_datetime_test.rb +0 -23
- data/test/bug2.rb +0 -10
- data/test/bug3.rb +0 -46
- data/test/bug_fast.rb +0 -32
- data/test/bug_load.rb +0 -24
- data/test/crash.rb +0 -111
- data/test/curl/curl_oj.rb +0 -46
- data/test/curl/get_oj.rb +0 -24
- data/test/curl/just_curl.rb +0 -31
- data/test/curl/just_oj.rb +0 -51
- data/test/example.rb +0 -11
- data/test/io.rb +0 -48
- data/test/isolated/test_mimic_rails_datetime.rb +0 -27
- data/test/mod.rb +0 -16
- data/test/rails.rb +0 -50
- data/test/russian.rb +0 -18
- data/test/struct.rb +0 -29
- data/test/test_serializer.rb +0 -59
- data/test/write_timebars.rb +0 -31
data/test/bug.rb
CHANGED
|
@@ -1,51 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
$: << '.'
|
|
2
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
|
3
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
|
3
4
|
|
|
4
|
-
$: << File.dirname(__FILE__)
|
|
5
5
|
|
|
6
|
-
require '
|
|
6
|
+
#require 'bundler/setup'
|
|
7
|
+
require 'oj'
|
|
8
|
+
require 'active_support'
|
|
9
|
+
require 'active_support/time_with_zone'
|
|
10
|
+
require 'tzinfo'
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
@state = []
|
|
11
|
-
end
|
|
12
|
+
puts ActiveSupport::TimeWithZone
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
@state << {}
|
|
15
|
-
@state.last
|
|
16
|
-
end
|
|
14
|
+
json = File.read('./bug.json')
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
@state.pop
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def hash_set(h,k,v)
|
|
23
|
-
h.store(k,v)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def array_start
|
|
27
|
-
@state << []
|
|
28
|
-
@state.last
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def array_end
|
|
33
|
-
@state.pop
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def array_append(a,v)
|
|
37
|
-
a << v
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def add_value(v)
|
|
41
|
-
p v
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def error(message, line, column); p "ERROR: #{message}" end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
$handler = Handler.new
|
|
48
|
-
|
|
49
|
-
IO.popen("cat tst") { |p| puts Oj.sc_parse($handler, p) }
|
|
50
|
-
|
|
51
|
-
#File.open('tst', 'r') { |file| Oj.sc_parse($handler, file) }
|
|
16
|
+
Oj.load(json)
|
data/test/foo.rb
CHANGED
|
@@ -1,24 +1,77 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
# encoding: UTF-8
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
$: << '.'
|
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
$: << File.join(File.dirname(here), 'lib')
|
|
7
|
+
require "oj"
|
|
8
|
+
require "socket"
|
|
9
|
+
require 'io/nonblock'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
#pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
|
|
12
|
+
pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
|
|
13
|
+
at_exit { Process.kill 9, pid }
|
|
14
|
+
sleep 0.2
|
|
15
|
+
s = Socket.tcp("localhost", 7777)
|
|
16
|
+
s.nonblock = false
|
|
17
|
+
1_000_000.times do |x|
|
|
18
|
+
Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
|
|
19
|
+
end
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
=begin
|
|
22
|
+
IO.pipe do |r, w|
|
|
23
|
+
if fork
|
|
24
|
+
r.close
|
|
25
|
+
#w.nonblock = false
|
|
26
|
+
1_000_000.times do |i|
|
|
27
|
+
begin
|
|
28
|
+
Oj.to_stream(w, { x: i})
|
|
29
|
+
rescue IOError => e
|
|
30
|
+
puts "*** #{i} raised #{e.class}: #{e}"
|
|
31
|
+
IO.select(nil, [w])
|
|
32
|
+
retry
|
|
33
|
+
end
|
|
34
|
+
w.puts
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
w.close
|
|
38
|
+
sleep(0.1)
|
|
39
|
+
r.each_line { |b|
|
|
40
|
+
#print b
|
|
41
|
+
}
|
|
42
|
+
r.close
|
|
43
|
+
Process.exit(0)
|
|
18
44
|
end
|
|
19
45
|
end
|
|
46
|
+
=end
|
|
20
47
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
=begin
|
|
49
|
+
IO.pipe do |r, w|
|
|
50
|
+
if fork
|
|
51
|
+
r.close
|
|
52
|
+
#w.nonblock = false
|
|
53
|
+
a = []
|
|
54
|
+
10_000.times do |i|
|
|
55
|
+
a << i
|
|
56
|
+
end
|
|
57
|
+
begin
|
|
58
|
+
Oj.to_stream(w, a, indent: 2)
|
|
59
|
+
rescue IOError => e
|
|
60
|
+
puts "*** raised #{e.class}: #{e}"
|
|
61
|
+
puts "*** fileno: #{w.fileno}"
|
|
62
|
+
puts "*** is an IO?: #{w.kind_of?(IO)}"
|
|
63
|
+
IO.select(nil, [w])
|
|
64
|
+
retry
|
|
65
|
+
end
|
|
66
|
+
w.puts
|
|
67
|
+
else
|
|
68
|
+
w.close
|
|
69
|
+
sleep(0.5)
|
|
70
|
+
r.each_line { |b|
|
|
71
|
+
#print b
|
|
72
|
+
}
|
|
73
|
+
r.close
|
|
74
|
+
Process.exit(0)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
=end
|
data/test/helper.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
1
3
|
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
|
2
4
|
# required. That can be set in the RUBYOPT environment variable.
|
|
3
5
|
# export RUBYOPT=-w
|
|
@@ -8,7 +10,6 @@ $VERBOSE = true
|
|
|
8
10
|
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
|
9
11
|
end
|
|
10
12
|
|
|
11
|
-
require 'rubygems' if RUBY_VERSION.start_with?('1.8.')
|
|
12
13
|
require 'minitest'
|
|
13
14
|
require 'minitest/autorun'
|
|
14
15
|
require 'stringio'
|
|
@@ -17,6 +18,14 @@ require 'bigdecimal'
|
|
|
17
18
|
require 'pp'
|
|
18
19
|
require 'oj'
|
|
19
20
|
|
|
21
|
+
|
|
22
|
+
if defined?(GC.verify_compaction_references) == 'method'
|
|
23
|
+
# This method was added in Ruby 3.0.0. Calling it this way asks the GC to
|
|
24
|
+
# move objects around, helping to find object movement bugs.
|
|
25
|
+
GC.verify_compaction_references(double_heap: true, toward: :empty)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
20
29
|
$ruby = RUBY_DESCRIPTION.split(' ')[0]
|
|
21
30
|
$ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
|
|
22
31
|
|
data/test/isolated/shared.rb
CHANGED
|
@@ -36,8 +36,6 @@ class SharedMimicTest < Minitest::Test
|
|
|
36
36
|
@expected_time_string =
|
|
37
37
|
if defined?(Rails)
|
|
38
38
|
%{"2014-05-13T16:53:20.000Z"}
|
|
39
|
-
elsif RUBY_VERSION.start_with?('1.8')
|
|
40
|
-
%{"Tue May 13 16:53:20 UTC 2014"}
|
|
41
39
|
else
|
|
42
40
|
%{"2014-05-13 16:53:20 UTC"}
|
|
43
41
|
end
|
|
@@ -145,7 +143,7 @@ class SharedMimicTest < Minitest::Test
|
|
|
145
143
|
Oj.mimic_JSON
|
|
146
144
|
children = []
|
|
147
145
|
json = %{{"a":1,"b":[true,false]}}
|
|
148
|
-
if 'rubinius' == $ruby
|
|
146
|
+
if 'rubinius' == $ruby
|
|
149
147
|
obj = JSON.load(json) {|x| children << x }
|
|
150
148
|
else
|
|
151
149
|
p = Proc.new {|x| children << x }
|
|
@@ -164,6 +162,12 @@ class SharedMimicTest < Minitest::Test
|
|
|
164
162
|
assert_raises(JSON::ParserError) { JSON.parse(json) }
|
|
165
163
|
end
|
|
166
164
|
|
|
165
|
+
def test_parse_with_empty_string
|
|
166
|
+
Oj.mimic_JSON
|
|
167
|
+
assert_raises(JSON::ParserError) { JSON.parse(' ') }
|
|
168
|
+
assert_raises(JSON::ParserError) { JSON.parse("\t\t\n ") }
|
|
169
|
+
end
|
|
170
|
+
|
|
167
171
|
# []
|
|
168
172
|
def test_bracket_load
|
|
169
173
|
json = %{{"a":1,"b":[true,false]}}
|
|
@@ -217,18 +221,18 @@ class SharedMimicTest < Minitest::Test
|
|
|
217
221
|
def test_pretty_generate
|
|
218
222
|
json = JSON.pretty_generate({ 'a' => 1, 'b' => [true, false]})
|
|
219
223
|
assert(%{{
|
|
220
|
-
"a"
|
|
221
|
-
"b"
|
|
224
|
+
"a": 1,
|
|
225
|
+
"b": [
|
|
222
226
|
true,
|
|
223
227
|
false
|
|
224
228
|
]
|
|
225
229
|
}} == json ||
|
|
226
230
|
%{{
|
|
227
|
-
"b"
|
|
231
|
+
"b": [
|
|
228
232
|
true,
|
|
229
233
|
false
|
|
230
234
|
],
|
|
231
|
-
"a"
|
|
235
|
+
"a": 1
|
|
232
236
|
}} == json)
|
|
233
237
|
end
|
|
234
238
|
|
|
@@ -269,7 +273,7 @@ class SharedMimicTest < Minitest::Test
|
|
|
269
273
|
children = []
|
|
270
274
|
JSON.recurse_proc({ 'a' => 1, 'b' => [true, false]}) { |x| children << x }
|
|
271
275
|
# JRuby 1.7.0 rb_yield() is broken and converts the [true, false] array into true
|
|
272
|
-
unless 'jruby' == $ruby
|
|
276
|
+
unless 'jruby' == $ruby
|
|
273
277
|
assert([1, true, false, [true, false], { 'a' => 1, 'b' => [true, false]}] == children ||
|
|
274
278
|
[true, false, [true, false], 1, { 'b' => [true, false], 'a' => 1}] == children)
|
|
275
279
|
end
|
|
@@ -7,9 +7,9 @@ require 'helper'
|
|
|
7
7
|
|
|
8
8
|
begin
|
|
9
9
|
require 'rails/all'
|
|
10
|
-
rescue
|
|
11
|
-
puts "
|
|
12
|
-
Process.exit
|
|
10
|
+
rescue LoadError => e
|
|
11
|
+
puts "Rails are not in the gemfile, skipping tests"
|
|
12
|
+
Process.exit
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
Oj.mimic_JSON
|
|
@@ -8,9 +8,9 @@ require 'helper'
|
|
|
8
8
|
Oj.mimic_JSON
|
|
9
9
|
begin
|
|
10
10
|
require 'rails/all'
|
|
11
|
-
rescue
|
|
12
|
-
puts "
|
|
13
|
-
Process.exit
|
|
11
|
+
rescue LoadError => e
|
|
12
|
+
puts "Rails are not in the gemfile, skipping tests"
|
|
13
|
+
Process.exit
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
require 'isolated/shared'
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
#frozen_string_literal: false
|
|
5
|
+
|
|
6
|
+
require 'json_gem/test_helper'
|
|
7
|
+
require 'date'
|
|
8
|
+
|
|
9
|
+
if REAL_JSON_GEM
|
|
10
|
+
require 'json/add/core'
|
|
11
|
+
require 'json/add/complex'
|
|
12
|
+
require 'json/add/rational'
|
|
13
|
+
require 'json/add/bigdecimal'
|
|
14
|
+
require 'json/add/ostruct'
|
|
15
|
+
else
|
|
16
|
+
#Oj.add_to_json()
|
|
17
|
+
Oj.add_to_json(Array, BigDecimal, Complex, Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational, Regexp, Struct, Time)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class JSONAdditionTest < Test::Unit::TestCase
|
|
21
|
+
include Test::Unit::TestCaseOmissionSupport
|
|
22
|
+
include Test::Unit::TestCasePendingSupport
|
|
23
|
+
|
|
24
|
+
class A
|
|
25
|
+
def self.json_creatable?
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize(a)
|
|
30
|
+
@a = a
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :a
|
|
34
|
+
|
|
35
|
+
def ==(other)
|
|
36
|
+
a == other.a
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.json_create(object)
|
|
40
|
+
new(*object['args'])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def to_json(*args)
|
|
44
|
+
{
|
|
45
|
+
'json_class' => self.class.name,
|
|
46
|
+
'args' => [ @a ],
|
|
47
|
+
}.to_json(*args)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class A2 < A
|
|
52
|
+
def to_json(*args)
|
|
53
|
+
{
|
|
54
|
+
'json_class' => self.class.name,
|
|
55
|
+
'args' => [ @a ],
|
|
56
|
+
}.to_json(*args)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class B
|
|
61
|
+
def self.json_creatable?
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_json(*args)
|
|
66
|
+
{
|
|
67
|
+
'json_class' => self.class.name,
|
|
68
|
+
}.to_json(*args)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class C
|
|
73
|
+
def self.json_creatable?
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_json(*args)
|
|
78
|
+
{
|
|
79
|
+
'json_class' => 'JSONAdditionTest::Nix',
|
|
80
|
+
}.to_json(*args)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_extended_json
|
|
85
|
+
a = A.new(666)
|
|
86
|
+
assert A.json_creatable?
|
|
87
|
+
json = JSON.generate(a)
|
|
88
|
+
a_again = JSON.parse(json, :create_additions => true)
|
|
89
|
+
assert_kind_of a.class, a_again
|
|
90
|
+
assert_equal a, a_again
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_extended_json_default
|
|
94
|
+
a = A.new(666)
|
|
95
|
+
assert A.json_creatable?
|
|
96
|
+
json = JSON.generate(a)
|
|
97
|
+
a_hash = JSON.parse(json)
|
|
98
|
+
assert_kind_of Hash, a_hash
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_extended_json_disabled
|
|
102
|
+
a = A.new(666)
|
|
103
|
+
assert A.json_creatable?
|
|
104
|
+
json = JSON.generate(a)
|
|
105
|
+
a_again = JSON.parse(json, :create_additions => true)
|
|
106
|
+
assert_kind_of a.class, a_again
|
|
107
|
+
assert_equal a, a_again
|
|
108
|
+
a_hash = JSON.parse(json, :create_additions => false)
|
|
109
|
+
assert_kind_of Hash, a_hash
|
|
110
|
+
assert_equal(
|
|
111
|
+
{"args"=>[666], "json_class"=>"JSONAdditionTest::A"}.sort_by { |k,| k },
|
|
112
|
+
a_hash.sort_by { |k,| k }
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_extended_json_fail1
|
|
117
|
+
b = B.new
|
|
118
|
+
assert !B.json_creatable?
|
|
119
|
+
json = JSON.generate(b)
|
|
120
|
+
assert_equal({ "json_class"=>"JSONAdditionTest::B" }, JSON.parse(json))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_extended_json_fail2
|
|
124
|
+
c = C.new
|
|
125
|
+
assert !C.json_creatable?
|
|
126
|
+
json = JSON.generate(c)
|
|
127
|
+
assert_raise(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_raw_strings
|
|
131
|
+
raw = ''
|
|
132
|
+
raw.respond_to?(:encode!) and raw.encode!(Encoding::ASCII_8BIT)
|
|
133
|
+
raw_array = []
|
|
134
|
+
for i in 0..255
|
|
135
|
+
raw << i
|
|
136
|
+
raw_array << i
|
|
137
|
+
end
|
|
138
|
+
json = raw.to_json_raw
|
|
139
|
+
json_raw_object = raw.to_json_raw_object
|
|
140
|
+
hash = { 'json_class' => 'String', 'raw'=> raw_array }
|
|
141
|
+
assert_equal hash, json_raw_object
|
|
142
|
+
assert_match(/\A\{.*\}\z/, json)
|
|
143
|
+
assert_match(/"json_class":"String"/, json)
|
|
144
|
+
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)
|
|
145
|
+
|
|
146
|
+
raw_again = JSON.parse(json, :create_additions => true)
|
|
147
|
+
assert_equal raw, raw_again
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
|
|
151
|
+
|
|
152
|
+
def test_core
|
|
153
|
+
t = Time.now
|
|
154
|
+
assert_equal t, JSON(JSON(t), :create_additions => true)
|
|
155
|
+
|
|
156
|
+
d = Date.today
|
|
157
|
+
assert_equal d, JSON(JSON(d), :create_additions => true)
|
|
158
|
+
|
|
159
|
+
d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
|
|
160
|
+
assert_equal d, JSON(JSON(d), :create_additions => true)
|
|
161
|
+
|
|
162
|
+
assert_equal 1..10, JSON(JSON(1..10), :create_additions => true)
|
|
163
|
+
assert_equal 1...10, JSON(JSON(1...10), :create_additions => true)
|
|
164
|
+
assert_equal "a".."c", JSON(JSON("a".."c"), :create_additions => true)
|
|
165
|
+
assert_equal "a"..."c", JSON(JSON("a"..."c"), :create_additions => true)
|
|
166
|
+
|
|
167
|
+
s = MyJsonStruct.new 4711, 'foot'
|
|
168
|
+
assert_equal s, JSON(JSON(s), :create_additions => true)
|
|
169
|
+
|
|
170
|
+
struct = Struct.new :foo, :bar
|
|
171
|
+
s = struct.new 4711, 'foot'
|
|
172
|
+
assert_raise(JSON::JSONError) { JSON(s) }
|
|
173
|
+
|
|
174
|
+
begin
|
|
175
|
+
raise TypeError, "test me"
|
|
176
|
+
rescue TypeError => e
|
|
177
|
+
e_json = JSON.generate e
|
|
178
|
+
e_again = JSON e_json, :create_additions => true
|
|
179
|
+
assert_kind_of TypeError, e_again
|
|
180
|
+
assert_equal e.message, e_again.message
|
|
181
|
+
assert_equal e.backtrace, e_again.backtrace
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
assert_equal(/foo/, JSON(JSON(/foo/), :create_additions => true))
|
|
185
|
+
assert_equal(/foo/i, JSON(JSON(/foo/i), :create_additions => true))
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def test_utc_datetime
|
|
189
|
+
now = Time.now
|
|
190
|
+
d = DateTime.parse(now.to_s, :create_additions => true) # usual case
|
|
191
|
+
assert_equal d, JSON.parse(d.to_json, :create_additions => true)
|
|
192
|
+
d = DateTime.parse(now.utc.to_s) # of = 0
|
|
193
|
+
assert_equal d, JSON.parse(d.to_json, :create_additions => true)
|
|
194
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
|
|
195
|
+
assert_equal d, JSON.parse(d.to_json, :create_additions => true)
|
|
196
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
|
|
197
|
+
assert_equal d, JSON.parse(d.to_json, :create_additions => true)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_rational_complex
|
|
201
|
+
assert_equal Rational(2, 9), JSON.parse(JSON(Rational(2, 9)), :create_additions => true)
|
|
202
|
+
assert_equal Complex(2, 9), JSON.parse(JSON(Complex(2, 9)), :create_additions => true)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def test_bigdecimal
|
|
206
|
+
assert_equal BigDecimal('3.141', 23), JSON(JSON(BigDecimal('3.141', 23)), :create_additions => true)
|
|
207
|
+
assert_equal BigDecimal('3.141', 666), JSON(JSON(BigDecimal('3.141', 666)), :create_additions => true)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def test_ostruct
|
|
211
|
+
o = OpenStruct.new
|
|
212
|
+
# XXX this won't work; o.foo = { :bar => true }
|
|
213
|
+
o.foo = { 'bar' => true }
|
|
214
|
+
assert_equal o, JSON.parse(JSON(o), :create_additions => true)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
#frozen_string_literal: false
|
|
5
|
+
|
|
6
|
+
require 'json_gem/test_helper'
|
|
7
|
+
|
|
8
|
+
require 'stringio'
|
|
9
|
+
require 'tempfile'
|
|
10
|
+
|
|
11
|
+
class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
12
|
+
include Test::Unit::TestCaseOmissionSupport
|
|
13
|
+
include Test::Unit::TestCasePendingSupport
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@hash = {
|
|
17
|
+
'a' => 2,
|
|
18
|
+
#'b' => 5.23683071,
|
|
19
|
+
'c' => 'c',
|
|
20
|
+
'd' => [ 1, "b", 3.14 ],
|
|
21
|
+
'e' => { 'foo' => 'bar' },
|
|
22
|
+
'g' => "\"\0\037",
|
|
23
|
+
'h' => 1000.0,
|
|
24
|
+
'i' => 0.001
|
|
25
|
+
}
|
|
26
|
+
# Tired of chasing floating point rounding and precision. Oj now uses the
|
|
27
|
+
# Ruby float parser in compat mode yet on i386 machines there are issues
|
|
28
|
+
# with this test when the float is included.
|
|
29
|
+
#@json = '{"a":2,"b":5.23683071,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
|
|
30
|
+
#'"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
|
|
31
|
+
@json = '{"a":2,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
|
|
32
|
+
'"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_index
|
|
36
|
+
assert_equal @json, JSON[@hash]
|
|
37
|
+
assert_equal @hash, JSON[@json]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
##############################################################################
|
|
41
|
+
# The next tests are omitted as implementing them and using them is a
|
|
42
|
+
# performance hit. Use of the JSON.parse() and similar provide the same
|
|
43
|
+
# functionality and perform better.
|
|
44
|
+
|
|
45
|
+
def test_parser
|
|
46
|
+
assert_match /::Parser\z/, JSON.parser.name
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_generator
|
|
50
|
+
assert_match /::Generator\z/, JSON.generator.name
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_state
|
|
54
|
+
assert_match /::Generator::State\z/, JSON.state.name
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# This doesn't have anything to do with JSON parsing or generation. It seems
|
|
58
|
+
# to be more of an internal tool that is exposed to users.
|
|
59
|
+
def test_deep_const_get
|
|
60
|
+
omit("mimic_JSON") unless REAL_JSON_GEM
|
|
61
|
+
assert_raise(ArgumentError) { JSON.deep_const_get('Nix::Da') }
|
|
62
|
+
assert_equal File::SEPARATOR, JSON.deep_const_get('File::SEPARATOR')
|
|
63
|
+
end
|
|
64
|
+
##############################################################################
|
|
65
|
+
|
|
66
|
+
def test_create_id
|
|
67
|
+
assert_equal 'json_class', JSON.create_id
|
|
68
|
+
JSON.create_id = 'foo_bar'
|
|
69
|
+
assert_equal 'foo_bar', JSON.create_id
|
|
70
|
+
ensure
|
|
71
|
+
JSON.create_id = 'json_class'
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_parse
|
|
75
|
+
assert_equal [ 1, 2, 3, ], JSON.parse('[ 1, 2, 3 ]')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_parse_bang
|
|
79
|
+
# Modified this test to compare strings since NaN comparison fails if NaN
|
|
80
|
+
# was defined in different places even if it represents the same value.
|
|
81
|
+
assert_equal [ 1, NaN, 3, ].to_s, JSON.parse!('[ 1, NaN, 3 ]').to_s
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_generate
|
|
85
|
+
assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_fast_generate
|
|
89
|
+
assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_pretty_generate
|
|
93
|
+
assert_equal "[\n 1,\n 2,\n 3\n]", JSON.pretty_generate([ 1, 2, 3 ])
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_load
|
|
97
|
+
assert_equal @hash, JSON.load(@json)
|
|
98
|
+
tempfile = Tempfile.open('@json')
|
|
99
|
+
tempfile.write @json
|
|
100
|
+
tempfile.rewind
|
|
101
|
+
assert_equal @hash, JSON.load(tempfile)
|
|
102
|
+
stringio = StringIO.new(@json)
|
|
103
|
+
stringio.rewind
|
|
104
|
+
assert_equal @hash, JSON.load(stringio)
|
|
105
|
+
assert_equal nil, JSON.load(nil)
|
|
106
|
+
assert_equal nil, JSON.load('')
|
|
107
|
+
ensure
|
|
108
|
+
tempfile.close!
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_load_with_options
|
|
112
|
+
json = '{ "foo": NaN }'
|
|
113
|
+
assert JSON.load(json, nil, :allow_nan => true)['foo'].nan?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_load_null
|
|
117
|
+
assert_equal nil, JSON.load(nil, nil, :allow_blank => true)
|
|
118
|
+
assert_raise(TypeError) { JSON.load(nil, nil, :allow_blank => false) }
|
|
119
|
+
assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
|
|
120
|
+
# The next tests are added by Oj to catch additional cases.
|
|
121
|
+
assert_equal nil, JSON.load('', nil, :allow_blank => true)
|
|
122
|
+
assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
|
|
123
|
+
assert_raise(JSON::ParserError) { JSON.load(' ', nil, :allow_blank => true) }
|
|
124
|
+
assert_raise(JSON::ParserError) { JSON.load(' ', nil, :allow_blank => false) }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_dump
|
|
128
|
+
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
|
|
129
|
+
assert_equal too_deep, JSON.dump(eval(too_deep))
|
|
130
|
+
assert_kind_of String, Marshal.dump(eval(too_deep))
|
|
131
|
+
assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
|
|
132
|
+
assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
|
|
133
|
+
assert_equal too_deep, JSON.dump(eval(too_deep), 101)
|
|
134
|
+
assert_kind_of String, Marshal.dump(eval(too_deep), 101)
|
|
135
|
+
output = StringIO.new
|
|
136
|
+
JSON.dump(eval(too_deep), output)
|
|
137
|
+
assert_equal too_deep, output.string
|
|
138
|
+
output = StringIO.new
|
|
139
|
+
JSON.dump(eval(too_deep), output, 101)
|
|
140
|
+
assert_equal too_deep, output.string
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_dump_should_modify_defaults
|
|
144
|
+
max_nesting = JSON.dump_default_options[:max_nesting]
|
|
145
|
+
JSON.dump([], StringIO.new, 10)
|
|
146
|
+
assert_equal max_nesting, JSON.dump_default_options[:max_nesting]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_JSON
|
|
150
|
+
assert_equal @json, JSON(@hash)
|
|
151
|
+
assert_equal @hash, JSON(@json)
|
|
152
|
+
end
|
|
153
|
+
end
|