oj 2.9.0 → 2.9.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +7 -7
- data/README.md +9 -4
- data/ext/oj/buf.h +1 -1
- data/ext/oj/compat.c +8 -8
- data/ext/oj/dump.c +18 -3
- data/ext/oj/err.h +1 -1
- data/ext/oj/object.c +19 -10
- data/ext/oj/oj.c +37 -31
- data/ext/oj/oj.h +2 -0
- data/ext/oj/parse.c +10 -7
- data/ext/oj/parse.h +11 -1
- data/ext/oj/reader.c +244 -0
- data/ext/oj/reader.h +173 -0
- data/ext/oj/sparse.c +803 -0
- data/ext/oj/strict.c +6 -2
- data/ext/oj/val_stack.h +3 -0
- data/lib/oj/version.rb +1 -1
- data/test/a.rb +38 -0
- data/test/bug.rb +17 -0
- data/test/e.rb +12 -0
- data/test/foo.rb +24 -0
- data/test/lots.rb +68 -0
- data/test/mj.rb +48 -0
- data/test/perf_file.rb +64 -0
- data/test/perf_object.rb +2 -1
- data/test/perf_str.rb +38 -0
- data/test/perf_strictx.rb +97 -0
- data/test/struct.rb +29 -0
- data/test/test_file.rb +242 -0
- data/test/test_mimic.rb +4 -7
- data/test/test_strictx.rb +58 -0
- data/test/tests.rb +34 -17
- data/test/x.rb +59 -0
- metadata +40 -31
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
data/test/struct.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
A = Struct.new(:a,:b,:c,:d)
|
16
|
+
B = Struct.new(:e,:f)
|
17
|
+
|
18
|
+
obj = [A.new(55, B.new(1, 'X'), B.new(2, 'Y'), 3)]
|
19
|
+
|
20
|
+
s = Oj.dump(obj, :mode => :object)
|
21
|
+
|
22
|
+
100000.times do
|
23
|
+
Oj.load(s, :mode => :object)
|
24
|
+
# ds = Oj.dump(o, :mode => :object)
|
25
|
+
# if ds != s
|
26
|
+
# puts ds
|
27
|
+
# raise "holy crap"
|
28
|
+
# end
|
29
|
+
end
|
data/test/test_file.rb
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'test/unit'
|
14
|
+
require 'date'
|
15
|
+
require 'bigdecimal'
|
16
|
+
require 'oj'
|
17
|
+
|
18
|
+
$ruby = RUBY_DESCRIPTION.split(' ')[0]
|
19
|
+
$ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
|
20
|
+
|
21
|
+
class Jam
|
22
|
+
attr_accessor :x, :y
|
23
|
+
|
24
|
+
def initialize(x, y)
|
25
|
+
@x = x
|
26
|
+
@y = y
|
27
|
+
end
|
28
|
+
|
29
|
+
def eql?(o)
|
30
|
+
self.class == o.class && @x == o.x && @y == o.y
|
31
|
+
end
|
32
|
+
alias == eql?
|
33
|
+
|
34
|
+
end# Jam
|
35
|
+
|
36
|
+
class Jeez < Jam
|
37
|
+
def initialize(x, y)
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_json()
|
42
|
+
%{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.json_create(h)
|
46
|
+
self.new(h['x'], h['y'])
|
47
|
+
end
|
48
|
+
end# Jeez
|
49
|
+
|
50
|
+
class Orange < Jam
|
51
|
+
def initialize(x, y)
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
def as_json()
|
56
|
+
{ :json_class => self.class,
|
57
|
+
:x => @x,
|
58
|
+
:y => @y }
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.json_create(h)
|
62
|
+
self.new(h['x'], h['y'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Range
|
67
|
+
def to_hash()
|
68
|
+
{ 'begin' => self.begin, 'end' => self.end, 'exclude_end' => self.exclude_end? }
|
69
|
+
end
|
70
|
+
end # Range
|
71
|
+
|
72
|
+
class FileJuice < ::Test::Unit::TestCase
|
73
|
+
|
74
|
+
def test_nil
|
75
|
+
dump_and_load(nil, false)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_true
|
79
|
+
dump_and_load(true, false)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_false
|
83
|
+
dump_and_load(false, false)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_fixnum
|
87
|
+
dump_and_load(0, false)
|
88
|
+
dump_and_load(12345, false)
|
89
|
+
dump_and_load(-54321, false)
|
90
|
+
dump_and_load(1, false)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_float
|
94
|
+
dump_and_load(0.0, false)
|
95
|
+
dump_and_load(12345.6789, false)
|
96
|
+
dump_and_load(70.35, false)
|
97
|
+
dump_and_load(-54321.012, false)
|
98
|
+
dump_and_load(2.48e16, false)
|
99
|
+
dump_and_load(2.48e100 * 1.0e10, false)
|
100
|
+
dump_and_load(-2.48e100 * 1.0e10, false)
|
101
|
+
dump_and_load(1/0.0, false)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_string
|
105
|
+
dump_and_load('', false)
|
106
|
+
dump_and_load('abc', false)
|
107
|
+
dump_and_load("abc\ndef", false)
|
108
|
+
dump_and_load("a\u0041", false)
|
109
|
+
assert_equal("a\u0000a", dump_and_load("a\u0000a", false))
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_string_object
|
113
|
+
dump_and_load('abc', false)
|
114
|
+
dump_and_load(':abc', false)
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_array
|
118
|
+
dump_and_load([], false)
|
119
|
+
dump_and_load([true, false], false)
|
120
|
+
dump_and_load(['a', 1, nil], false)
|
121
|
+
dump_and_load([[nil]], false)
|
122
|
+
dump_and_load([[nil], 58], false)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Symbol
|
126
|
+
def test_symbol_object
|
127
|
+
Oj.default_options = { :mode => :object }
|
128
|
+
#dump_and_load(''.to_sym, false)
|
129
|
+
dump_and_load(:abc, false)
|
130
|
+
dump_and_load(':xyz'.to_sym, false)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Time
|
134
|
+
def test_time_object
|
135
|
+
t = Time.now()
|
136
|
+
Oj.default_options = { :mode => :object }
|
137
|
+
dump_and_load(t, false)
|
138
|
+
end
|
139
|
+
def test_time_object_early
|
140
|
+
t = Time.xmlschema("1954-01-05T00:00:00.123456")
|
141
|
+
Oj.default_options = { :mode => :object }
|
142
|
+
dump_and_load(t, false)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Hash
|
146
|
+
def test_hash
|
147
|
+
Oj.default_options = { :mode => :strict }
|
148
|
+
dump_and_load({}, false)
|
149
|
+
dump_and_load({ 'true' => true, 'false' => false}, false)
|
150
|
+
dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Object with to_json()
|
154
|
+
def test_json_object_compat
|
155
|
+
Oj.default_options = { :mode => :compat, :use_to_json => true }
|
156
|
+
obj = Jeez.new(true, 58)
|
157
|
+
json = Oj.dump(obj, :indent => 2)
|
158
|
+
assert(%{{"json_class":"Jeez","x":true,"y":58}
|
159
|
+
} == json ||
|
160
|
+
%{{"json_class":"Jeez","y":58,"x":true}
|
161
|
+
} == json)
|
162
|
+
dump_and_load(obj, false)
|
163
|
+
Oj.default_options = { :mode => :compat, :use_to_json => false }
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_as_json_object_compat_hash
|
167
|
+
Oj.default_options = { :mode => :compat }
|
168
|
+
obj = Orange.new(true, 58)
|
169
|
+
json = Oj.dump(obj, :indent => 2)
|
170
|
+
assert(!json.nil?)
|
171
|
+
dump_and_load(obj, false)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Range
|
175
|
+
def test_range_object
|
176
|
+
unless RUBY_VERSION.start_with?('1.8')
|
177
|
+
Oj.default_options = { :mode => :object }
|
178
|
+
json = Oj.dump(1..7, :mode => :object, :indent => 0)
|
179
|
+
if 'rubinius' == $ruby
|
180
|
+
assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
|
181
|
+
elsif 'jruby' == $ruby
|
182
|
+
assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
|
183
|
+
else
|
184
|
+
assert_equal(%{{"^u":["Range",1,7,false]}}, json)
|
185
|
+
end
|
186
|
+
dump_and_load(1..7, false)
|
187
|
+
dump_and_load(1..1, false)
|
188
|
+
dump_and_load(1...7, false)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# BigNum
|
193
|
+
def test_bignum_object
|
194
|
+
Oj.default_options = { :mode => :compat }
|
195
|
+
dump_and_load(7 ** 55, false)
|
196
|
+
end
|
197
|
+
|
198
|
+
# BigDecimal
|
199
|
+
def test_bigdecimal_strict
|
200
|
+
mode = Oj.default_options[:mode]
|
201
|
+
Oj.default_options = {:mode => :strict}
|
202
|
+
dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
|
203
|
+
Oj.default_options = {:mode => mode}
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_bigdecimal_null
|
207
|
+
mode = Oj.default_options[:mode]
|
208
|
+
Oj.default_options = {:mode => :null}
|
209
|
+
dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
|
210
|
+
Oj.default_options = {:mode => mode}
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_bigdecimal_object
|
214
|
+
mode = Oj.default_options[:mode]
|
215
|
+
Oj.default_options = {:mode => :object}
|
216
|
+
dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Date
|
220
|
+
def test_date_object
|
221
|
+
Oj.default_options = { :mode => :object }
|
222
|
+
dump_and_load(Date.new(2012, 6, 19), false)
|
223
|
+
end
|
224
|
+
|
225
|
+
# DateTime
|
226
|
+
def test_datetime_object
|
227
|
+
Oj.default_options = { :mode => :object }
|
228
|
+
dump_and_load(DateTime.new(2012, 6, 19), false)
|
229
|
+
end
|
230
|
+
|
231
|
+
def dump_and_load(obj, trace=false)
|
232
|
+
filename = 'file_test.json'
|
233
|
+
File.open(filename, "w") { |f|
|
234
|
+
Oj.to_stream(f, obj, :indent => 2)
|
235
|
+
}
|
236
|
+
puts "\n*** file: '#{File.read(filename)}'" if trace
|
237
|
+
loaded = Oj.load_file(filename)
|
238
|
+
assert_equal(obj, loaded)
|
239
|
+
loaded
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
data/test/test_mimic.rb
CHANGED
@@ -80,19 +80,16 @@ class Mimic < ::Test::Unit::TestCase
|
|
80
80
|
Oj.mimic_JSON # TBD
|
81
81
|
children = []
|
82
82
|
json = %{{"a":1,"b":[true,false]}}
|
83
|
-
if 'rubinius' == $ruby || '
|
83
|
+
if 'rubinius' == $ruby || '1.8.7' == RUBY_VERSION
|
84
84
|
obj = JSON.load(json) {|x| children << x }
|
85
85
|
else
|
86
86
|
p = Proc.new {|x| children << x }
|
87
87
|
obj = JSON.load(json, p)
|
88
88
|
end
|
89
89
|
assert_equal({ 'a' => 1, 'b' => [true, false]}, obj)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
[true, false, [true, false], 1, { 'a' => 1, 'b' => [true, false]}] == children,
|
94
|
-
"children don't match")
|
95
|
-
end
|
90
|
+
assert([1, true, false, [true, false], { 'a' => 1, 'b' => [true, false]}] == children ||
|
91
|
+
[true, false, [true, false], 1, { 'a' => 1, 'b' => [true, false]}] == children,
|
92
|
+
"children don't match")
|
96
93
|
end
|
97
94
|
|
98
95
|
# []
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
12
|
+
|
13
|
+
require 'test/unit'
|
14
|
+
require 'stringio'
|
15
|
+
require 'date'
|
16
|
+
require 'oj'
|
17
|
+
|
18
|
+
$ruby = RUBY_DESCRIPTION.split(' ')[0]
|
19
|
+
$ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
|
20
|
+
|
21
|
+
def hash_eql(h1, h2)
|
22
|
+
return false if h1.size != h2.size
|
23
|
+
h1.keys.each do |k|
|
24
|
+
return false unless h1[k] == h2[k]
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
class StrictJuice < ::Test::Unit::TestCase
|
30
|
+
|
31
|
+
# Stream IO
|
32
|
+
def test_io_string
|
33
|
+
json = %{{
|
34
|
+
"x":true,
|
35
|
+
"y":58,
|
36
|
+
"z": [1,2,3]
|
37
|
+
}
|
38
|
+
}
|
39
|
+
input = StringIO.new(json)
|
40
|
+
obj = Oj.strict_loadx(input)
|
41
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
42
|
+
end
|
43
|
+
|
44
|
+
def xtest_io_file
|
45
|
+
filename = 'open_file_test.json'
|
46
|
+
File.open(filename, 'w') { |f| f.write(%{{
|
47
|
+
"x":true,
|
48
|
+
"y":58,
|
49
|
+
"z": [1,2,3]
|
50
|
+
}
|
51
|
+
}) }
|
52
|
+
f = File.new(filename)
|
53
|
+
obj = Oj.strict_loadx(f)
|
54
|
+
f.close()
|
55
|
+
assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/test/tests.rb
CHANGED
@@ -570,8 +570,10 @@ class Juice < ::Test::Unit::TestCase
|
|
570
570
|
Oj.default_options = { :mode => :compat, :use_to_json => true }
|
571
571
|
obj = Jeez.new(true, 58)
|
572
572
|
json = Oj.dump(obj, :indent => 2)
|
573
|
-
assert(%{{"json_class":"Jeez","x":true,"y":58}
|
574
|
-
|
573
|
+
assert(%{{"json_class":"Jeez","x":true,"y":58}
|
574
|
+
} == json ||
|
575
|
+
%{{"json_class":"Jeez","y":58,"x":true}
|
576
|
+
} == json)
|
575
577
|
dump_and_load(obj, false)
|
576
578
|
Oj.default_options = { :mode => :compat, :use_to_json => false }
|
577
579
|
end
|
@@ -590,12 +592,14 @@ class Juice < ::Test::Unit::TestCase
|
|
590
592
|
"^o":"Jeez",
|
591
593
|
"x":true,
|
592
594
|
"y":58
|
593
|
-
}
|
595
|
+
}
|
596
|
+
} == json ||
|
594
597
|
%{{
|
595
598
|
"^o":"Jeez",
|
596
599
|
"y":58,
|
597
600
|
"x":true
|
598
|
-
}
|
601
|
+
}
|
602
|
+
} == json)
|
599
603
|
obj2 = Oj.load(json, :mode => :object)
|
600
604
|
assert_equal(obj, obj2)
|
601
605
|
end
|
@@ -629,12 +633,14 @@ class Juice < ::Test::Unit::TestCase
|
|
629
633
|
"^o":"Jazz",
|
630
634
|
"x":true,
|
631
635
|
"y":58
|
632
|
-
}
|
636
|
+
}
|
637
|
+
} == json ||
|
633
638
|
%{{
|
634
639
|
"^o":"Jazz",
|
635
640
|
"y":58,
|
636
641
|
"x":true
|
637
|
-
}
|
642
|
+
}
|
643
|
+
} == json)
|
638
644
|
obj2 = Oj.load(json, :mode => :object)
|
639
645
|
assert_equal(obj, obj2)
|
640
646
|
end
|
@@ -679,12 +685,14 @@ class Juice < ::Test::Unit::TestCase
|
|
679
685
|
"^o":"Orange",
|
680
686
|
"x":true,
|
681
687
|
"y":58
|
682
|
-
}
|
688
|
+
}
|
689
|
+
} == json ||
|
683
690
|
%{{
|
684
691
|
"^o":"Orange",
|
685
692
|
"y":58,
|
686
693
|
"x":true
|
687
|
-
}
|
694
|
+
}
|
695
|
+
} == json)
|
688
696
|
obj2 = Oj.load(json, :mode => :object)
|
689
697
|
assert_equal(obj, obj2)
|
690
698
|
end
|
@@ -711,11 +719,13 @@ class Juice < ::Test::Unit::TestCase
|
|
711
719
|
assert(%{{
|
712
720
|
"x":true,
|
713
721
|
"y":58
|
714
|
-
}
|
722
|
+
}
|
723
|
+
} == json ||
|
715
724
|
%{{
|
716
725
|
"y":58,
|
717
726
|
"x":true
|
718
|
-
}
|
727
|
+
}
|
728
|
+
} == json)
|
719
729
|
end
|
720
730
|
def test_object_object
|
721
731
|
obj = Jam.new(true, 58)
|
@@ -724,12 +734,14 @@ class Juice < ::Test::Unit::TestCase
|
|
724
734
|
"^o":"Jam",
|
725
735
|
"x":true,
|
726
736
|
"y":58
|
727
|
-
}
|
737
|
+
}
|
738
|
+
} == json ||
|
728
739
|
%{{
|
729
740
|
"^o":"Jam",
|
730
741
|
"y":58,
|
731
742
|
"x":true
|
732
|
-
}
|
743
|
+
}
|
744
|
+
} == json)
|
733
745
|
obj2 = Oj.load(json, :mode => :object)
|
734
746
|
assert_equal(obj, obj2)
|
735
747
|
end
|
@@ -741,12 +753,14 @@ class Juice < ::Test::Unit::TestCase
|
|
741
753
|
"^o":"Jam",
|
742
754
|
"x":true,
|
743
755
|
"y":58
|
744
|
-
}
|
756
|
+
}
|
757
|
+
} == json ||
|
745
758
|
%{{
|
746
759
|
"^o":"Jam",
|
747
760
|
"y":58,
|
748
761
|
"x":true
|
749
|
-
}
|
762
|
+
}
|
763
|
+
} == json)
|
750
764
|
obj2 = Oj.load(json, :mode => :object, :class_cache => false)
|
751
765
|
assert_equal(obj, obj2)
|
752
766
|
end
|
@@ -969,13 +983,15 @@ class Juice < ::Test::Unit::TestCase
|
|
969
983
|
"^i":1,
|
970
984
|
"x":"^r1",
|
971
985
|
"y":58
|
972
|
-
}
|
986
|
+
}
|
987
|
+
} == json ||
|
973
988
|
%{{
|
974
989
|
"^o":"Jam",
|
975
990
|
"^i":1,
|
976
991
|
"y":58,
|
977
992
|
"x":"^r1"
|
978
|
-
}
|
993
|
+
}
|
994
|
+
} == json)
|
979
995
|
obj2 = Oj.load(json, :mode => :object, :circular => true)
|
980
996
|
assert_equal(obj2.x.__id__, obj2.__id__)
|
981
997
|
end
|
@@ -998,7 +1014,8 @@ class Juice < ::Test::Unit::TestCase
|
|
998
1014
|
"^i1",
|
999
1015
|
7,
|
1000
1016
|
"^r1"
|
1001
|
-
]
|
1017
|
+
]
|
1018
|
+
}, json)
|
1002
1019
|
a2 = Oj.load(json, :mode => :object, :circular => true)
|
1003
1020
|
assert_equal(a2[1].__id__, a2.__id__)
|
1004
1021
|
end
|