oj 2.8.0 → 2.8.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.
- data/README.md +4 -5
- data/ext/oj/dump.c +4 -3
- data/ext/oj/odd.c +2 -2
- data/ext/oj/odd.h +1 -1
- data/ext/oj/oj.c +9 -7
- data/ext/oj/parse.c +4 -2
- data/ext/oj/saj.c +5 -3
- data/lib/oj/version.rb +1 -1
- data/test/perf1.rb +64 -0
- data/test/perf2.rb +76 -0
- data/test/perf_obj_old.rb +213 -0
- data/test/test_object.rb +1 -1
- metadata +35 -38
- checksums.yaml +0 -7
- data/test/a.rb +0 -38
- data/test/bug.rb +0 -17
- data/test/e.rb +0 -12
- data/test/foo.rb +0 -24
- data/test/lots.rb +0 -68
- data/test/mj.rb +0 -48
- data/test/struct.rb +0 -29
- data/test/x.rb +0 -59
data/README.md
CHANGED
@@ -26,12 +26,11 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
|
|
26
26
|
|
27
27
|
[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
|
28
28
|
|
29
|
-
### Current Release 2.8.
|
29
|
+
### Current Release 2.8.1
|
30
30
|
|
31
|
-
- Added
|
32
|
-
|
33
|
-
|
34
|
-
`test_odd_string` test.
|
31
|
+
- Added additional argument to the register_odd function.
|
32
|
+
|
33
|
+
- Fixed bug that failed to load on some uses of STDIN.
|
35
34
|
|
36
35
|
[Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
|
37
36
|
|
data/ext/oj/dump.c
CHANGED
@@ -1779,6 +1779,7 @@ oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
1779
1779
|
struct _Out out;
|
1780
1780
|
ssize_t size;
|
1781
1781
|
VALUE clas = rb_obj_class(stream);
|
1782
|
+
int fd;
|
1782
1783
|
#if !IS_WINDOWS
|
1783
1784
|
VALUE s;
|
1784
1785
|
#endif
|
@@ -1791,9 +1792,9 @@ oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
1791
1792
|
if (oj_stringio_class == clas) {
|
1792
1793
|
rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
|
1793
1794
|
#if !IS_WINDOWS
|
1794
|
-
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
1795
|
-
|
1796
|
-
|
1795
|
+
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
1796
|
+
Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
|
1797
|
+
0 != (fd = FIX2INT(s))) {
|
1797
1798
|
if (size != write(fd, out.buf, size)) {
|
1798
1799
|
if (out.allocated) {
|
1799
1800
|
xfree(out.buf);
|
data/ext/oj/odd.c
CHANGED
@@ -162,7 +162,7 @@ oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
|
162
162
|
}
|
163
163
|
|
164
164
|
void
|
165
|
-
oj_reg_odd(VALUE clas, VALUE create_method, int mcnt, VALUE *members) {
|
165
|
+
oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members) {
|
166
166
|
Odd odd;
|
167
167
|
const char **np;
|
168
168
|
ID *ap;
|
@@ -178,7 +178,7 @@ oj_reg_odd(VALUE clas, VALUE create_method, int mcnt, VALUE *members) {
|
|
178
178
|
odd->clas = clas;
|
179
179
|
odd->classname = strdup(rb_class2name(clas));
|
180
180
|
odd->clen = strlen(odd->classname);
|
181
|
-
odd->create_obj =
|
181
|
+
odd->create_obj = create_object;
|
182
182
|
odd->create_op = SYM2ID(create_method);
|
183
183
|
odd->attr_cnt = mcnt;
|
184
184
|
for (ap = odd->attrs, np = odd->attr_names; 0 < mcnt; mcnt--, ap++, np++, members++) {
|
data/ext/oj/odd.h
CHANGED
@@ -57,6 +57,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
|
|
57
57
|
extern OddArgs oj_odd_alloc_args(Odd odd);
|
58
58
|
extern void oj_odd_free(OddArgs args);
|
59
59
|
extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
|
60
|
-
extern void oj_reg_odd(VALUE clas, VALUE create_method, int mcnt, VALUE *members);
|
60
|
+
extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members);
|
61
61
|
|
62
62
|
#endif /* __OJ_ODD_H__ */
|
data/ext/oj/oj.c
CHANGED
@@ -841,7 +841,7 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
841
841
|
return Qnil;
|
842
842
|
}
|
843
843
|
|
844
|
-
/* call-seq: register_odd(clas, create_method, *members)
|
844
|
+
/* call-seq: register_odd(clas, create_object, create_method, *members)
|
845
845
|
*
|
846
846
|
* Registers a class as special. This is useful for working around subclasses of
|
847
847
|
* primitive types as is done with ActiveSupport classes. The use of this
|
@@ -850,6 +850,7 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
850
850
|
* classes as it is not optimized for large numbers of classes.
|
851
851
|
*
|
852
852
|
* @param [Class] clas Class to me made special
|
853
|
+
* @param [Object] create_object object to call the create method on
|
853
854
|
* @param [Symbol] create_method method on the clas that will create a new
|
854
855
|
* instance of the clas when given all the member values in the
|
855
856
|
* order specified.
|
@@ -858,15 +859,15 @@ to_stream(int argc, VALUE *argv, VALUE self) {
|
|
858
859
|
*/
|
859
860
|
static VALUE
|
860
861
|
register_odd(int argc, VALUE *argv, VALUE self) {
|
861
|
-
if (
|
862
|
+
if (3 > argc) {
|
862
863
|
rb_raise(rb_eArgError, "incorrect number of arguments.");
|
863
864
|
}
|
864
865
|
Check_Type(argv[0], T_CLASS);
|
865
|
-
Check_Type(argv[
|
866
|
-
if (MAX_ODD_ARGS < argc -
|
866
|
+
Check_Type(argv[2], T_SYMBOL);
|
867
|
+
if (MAX_ODD_ARGS < argc - 2) {
|
867
868
|
rb_raise(rb_eArgError, "too many members.");
|
868
869
|
}
|
869
|
-
oj_reg_odd(argv[0], argv[1], argc -
|
870
|
+
oj_reg_odd(argv[0], argv[1], argv[2], argc - 3, argv + 3);
|
870
871
|
|
871
872
|
return Qnil;
|
872
873
|
}
|
@@ -1191,9 +1192,10 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
1191
1192
|
if (oj_stringio_class == clas) {
|
1192
1193
|
type = STRING_IO;
|
1193
1194
|
#if !IS_WINDOWS
|
1194
|
-
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
1195
|
+
} else if (rb_respond_to(stream, oj_fileno_id) &&
|
1196
|
+
Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
|
1197
|
+
0 != (fd = FIX2INT(s))) {
|
1195
1198
|
type = FILE_IO;
|
1196
|
-
fd = FIX2INT(s);
|
1197
1199
|
#endif
|
1198
1200
|
} else if (rb_respond_to(stream, oj_write_id)) {
|
1199
1201
|
type = STREAM_IO;
|
data/ext/oj/parse.c
CHANGED
@@ -747,14 +747,16 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len) {
|
|
747
747
|
} else {
|
748
748
|
VALUE clas = rb_obj_class(input);
|
749
749
|
volatile VALUE s;
|
750
|
+
int fd;
|
750
751
|
|
751
752
|
if (oj_stringio_class == clas) {
|
752
753
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
753
754
|
pi->json = rb_string_value_cstr((VALUE*)&s);
|
754
755
|
pi->end = pi->json + RSTRING_LEN(s);
|
755
756
|
#if !IS_WINDOWS
|
756
|
-
} else if (rb_respond_to(input, oj_fileno_id) &&
|
757
|
-
|
757
|
+
} else if (rb_respond_to(input, oj_fileno_id) &&
|
758
|
+
Qnil != (s = rb_funcall(input, oj_fileno_id, 0)) &&
|
759
|
+
0 != (fd = FIX2INT(s))) {
|
758
760
|
ssize_t cnt;
|
759
761
|
size_t len = lseek(fd, 0, SEEK_END);
|
760
762
|
|
data/ext/oj/saj.c
CHANGED
@@ -716,7 +716,8 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
716
716
|
} else {
|
717
717
|
VALUE clas = rb_obj_class(input);
|
718
718
|
volatile VALUE s;
|
719
|
-
|
719
|
+
int fd;
|
720
|
+
|
720
721
|
if (oj_stringio_class == clas) {
|
721
722
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
722
723
|
len = RSTRING_LEN(s) + 1;
|
@@ -725,8 +726,9 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
725
726
|
#ifndef JRUBY_RUBY
|
726
727
|
#if !IS_WINDOWS
|
727
728
|
// JRuby gets confused with what is the real fileno.
|
728
|
-
} else if (rb_respond_to(input, oj_fileno_id) &&
|
729
|
-
|
729
|
+
} else if (rb_respond_to(input, oj_fileno_id) &&
|
730
|
+
Qnil != (s = rb_funcall(input, oj_fileno_id, 0)) &&
|
731
|
+
0 != (fd = FIX2INT(s))) {
|
730
732
|
ssize_t cnt;
|
731
733
|
|
732
734
|
len = lseek(fd, 0, SEEK_END);
|
data/lib/oj/version.rb
CHANGED
data/test/perf1.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
|
7
|
+
#require 'test/unit'
|
8
|
+
require 'optparse'
|
9
|
+
require 'oj'
|
10
|
+
require 'ox'
|
11
|
+
|
12
|
+
$indent = 2
|
13
|
+
|
14
|
+
opts = OptionParser.new
|
15
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
16
|
+
files = opts.parse(ARGV)
|
17
|
+
|
18
|
+
iter = 100000
|
19
|
+
s = %{
|
20
|
+
{ "class": "Foo::Bar",
|
21
|
+
"attr1": [ true, [false, [12345, null], 3.967, ["something", false], null]],
|
22
|
+
"attr2": { "one": 1 }
|
23
|
+
}
|
24
|
+
}
|
25
|
+
#s = File.read('sample.json')
|
26
|
+
|
27
|
+
Oj.default_options = { :indent => 0 }
|
28
|
+
|
29
|
+
obj = Oj.load(s)
|
30
|
+
xml = Ox.dump(obj, :indent => 0)
|
31
|
+
|
32
|
+
puts xml
|
33
|
+
|
34
|
+
start = Time.now
|
35
|
+
iter.times do
|
36
|
+
Oj.load(s)
|
37
|
+
end
|
38
|
+
dt = Time.now - start
|
39
|
+
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
40
|
+
|
41
|
+
start = Time.now
|
42
|
+
iter.times do
|
43
|
+
Ox.load(xml)
|
44
|
+
end
|
45
|
+
dt = Time.now - start
|
46
|
+
puts "%d Ox.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
47
|
+
|
48
|
+
puts
|
49
|
+
|
50
|
+
start = Time.now
|
51
|
+
iter.times do
|
52
|
+
Oj.dump(obj)
|
53
|
+
end
|
54
|
+
dt = Time.now - start
|
55
|
+
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
56
|
+
|
57
|
+
start = Time.now
|
58
|
+
iter.times do
|
59
|
+
Ox.dump(obj)
|
60
|
+
end
|
61
|
+
dt = Time.now - start
|
62
|
+
puts "%d Ox.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
63
|
+
|
64
|
+
puts
|
data/test/perf2.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
|
7
|
+
#require 'test/unit'
|
8
|
+
require 'optparse'
|
9
|
+
require 'yajl'
|
10
|
+
require 'oj'
|
11
|
+
|
12
|
+
$indent = 2
|
13
|
+
|
14
|
+
opts = OptionParser.new
|
15
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
16
|
+
files = opts.parse(ARGV)
|
17
|
+
|
18
|
+
class Foo
|
19
|
+
def initialize()
|
20
|
+
@x = true
|
21
|
+
@y = 58
|
22
|
+
end
|
23
|
+
def to_json()
|
24
|
+
%{{"x":#{@x},"y":#{@y}}}
|
25
|
+
end
|
26
|
+
def to_hash()
|
27
|
+
{ 'x' => @x, 'y' => @y }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
iter = 100000
|
32
|
+
s = %{
|
33
|
+
{ "class": "Foo::Bar",
|
34
|
+
"attr1": [ true, [false, [12345, null], 3.967, ["something", false], null]],
|
35
|
+
"attr2": { "one": 1 }
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
obj = Oj.load(s)
|
40
|
+
obj["foo"] = Foo.new()
|
41
|
+
|
42
|
+
Oj.default_options = { :indent => 0, :effort => :internal }
|
43
|
+
|
44
|
+
puts
|
45
|
+
|
46
|
+
start = Time.now
|
47
|
+
iter.times do
|
48
|
+
Oj.load(s)
|
49
|
+
end
|
50
|
+
dt = Time.now - start
|
51
|
+
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
|
52
|
+
|
53
|
+
start = Time.now
|
54
|
+
iter.times do
|
55
|
+
Yajl::Parser.parse(s)
|
56
|
+
end
|
57
|
+
dt = Time.now - start
|
58
|
+
puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [iter, dt, iter/dt/1000.0]
|
59
|
+
|
60
|
+
puts
|
61
|
+
|
62
|
+
start = Time.now
|
63
|
+
iter.times do
|
64
|
+
Oj.dump(obj)
|
65
|
+
end
|
66
|
+
dt = Time.now - start
|
67
|
+
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
|
68
|
+
|
69
|
+
start = Time.now
|
70
|
+
iter.times do
|
71
|
+
Yajl::Encoder.encode(obj)
|
72
|
+
end
|
73
|
+
dt = Time.now - start
|
74
|
+
puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [iter, dt, iter/dt/1000.0]
|
75
|
+
|
76
|
+
puts
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
|
3
|
+
$: << '.'
|
4
|
+
$: << '..'
|
5
|
+
$: << '../lib'
|
6
|
+
$: << '../ext'
|
7
|
+
|
8
|
+
if __FILE__ == $0
|
9
|
+
if (i = ARGV.index('-I'))
|
10
|
+
x,path = ARGV.slice!(i, 2)
|
11
|
+
$: << path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'optparse'
|
16
|
+
require 'ox'
|
17
|
+
require 'oj'
|
18
|
+
require 'perf'
|
19
|
+
require 'sample'
|
20
|
+
require 'files'
|
21
|
+
|
22
|
+
$verbose = 0
|
23
|
+
$circular = false
|
24
|
+
$indent = 0
|
25
|
+
|
26
|
+
do_sample = false
|
27
|
+
do_files = false
|
28
|
+
|
29
|
+
do_load = false
|
30
|
+
do_dump = false
|
31
|
+
do_read = false
|
32
|
+
do_write = false
|
33
|
+
$iter = 1000
|
34
|
+
|
35
|
+
opts = OptionParser.new
|
36
|
+
opts.on("-v", "increase verbosity") { $verbose += 1 }
|
37
|
+
|
38
|
+
opts.on("-c", "circular options") { $circular = true }
|
39
|
+
|
40
|
+
opts.on("-s", "load and dump as sample Ruby object") { do_sample = true }
|
41
|
+
opts.on("-f", "load and dump as files Ruby object") { do_files = true }
|
42
|
+
|
43
|
+
opts.on("-l", "load") { do_load = true }
|
44
|
+
opts.on("-d", "dump") { do_dump = true }
|
45
|
+
opts.on("-r", "read") { do_read = true }
|
46
|
+
opts.on("-w", "write") { do_write = true }
|
47
|
+
opts.on("-a", "load, dump, read and write") { do_load = true; do_dump = true; do_read = true; do_write = true }
|
48
|
+
|
49
|
+
opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i }
|
50
|
+
|
51
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
52
|
+
files = opts.parse(ARGV)
|
53
|
+
|
54
|
+
if files.empty?
|
55
|
+
data = []
|
56
|
+
obj = do_sample ? sample_doc(2) : files('..')
|
57
|
+
mars = Marshal.dump(obj)
|
58
|
+
xml = Ox.dump(obj, :indent => $indent, circular: $circular)
|
59
|
+
json = Oj.dump(obj, :indent => $indent, circular: $circular)
|
60
|
+
File.open('sample.xml', 'w') { |f| f.write(xml) }
|
61
|
+
File.open('sample.json', 'w') { |f| f.write(json) }
|
62
|
+
File.open('sample.marshal', 'w') { |f| f.write(mars) }
|
63
|
+
data << { :file => 'sample.xml', :obj => obj, :xml => xml, :marshal => mars, :json => json }
|
64
|
+
else
|
65
|
+
puts "loading and parsing #{files}\n\n"
|
66
|
+
# TBD change to allow xml and json
|
67
|
+
data = files.map do |f|
|
68
|
+
xml = File.read(f)
|
69
|
+
obj = Ox.load(xml);
|
70
|
+
mars = Marshal.dump(obj)
|
71
|
+
json = Oj.dump(obj, :indent => $indent, circular: $circular)
|
72
|
+
{ :file => f, :obj => obj, :xml => xml, :marshal => mars, :json => json }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
$ox_load_time = 0
|
77
|
+
$mars_load_time = 0
|
78
|
+
$ox_dump_time = 0
|
79
|
+
$oj_dump_time = 0
|
80
|
+
$mars_dump_time = 0
|
81
|
+
|
82
|
+
def perf_load(d)
|
83
|
+
filename = d[:file]
|
84
|
+
marshal_filename = 'sample.marshal'
|
85
|
+
xml = d[:xml]
|
86
|
+
mars = d[:marshal]
|
87
|
+
json = d[:json]
|
88
|
+
|
89
|
+
if 0 < $verbose
|
90
|
+
obj = Ox.load(xml, :mode => :object, :trace => $verbose)
|
91
|
+
return
|
92
|
+
end
|
93
|
+
start = Time.now
|
94
|
+
(1..$iter).each do
|
95
|
+
obj = Ox.load(xml, :mode => :object)
|
96
|
+
end
|
97
|
+
$ox_load_time = Time.now - start
|
98
|
+
puts "Parsing #{$iter} times with Ox took #{$ox_load_time} seconds."
|
99
|
+
|
100
|
+
start = Time.now
|
101
|
+
(1..$iter).each do
|
102
|
+
obj = Oj.load(json, :mode => :object)
|
103
|
+
end
|
104
|
+
$oj_load_time = Time.now - start
|
105
|
+
puts "Parsing #{$iter} times with Oj took #{$oj_load_time} seconds."
|
106
|
+
|
107
|
+
start = Time.now
|
108
|
+
(1..$iter).each do
|
109
|
+
obj = Marshal.load(mars)
|
110
|
+
end
|
111
|
+
$mars_load_time = Time.now - start
|
112
|
+
puts "Marshalling #{$iter} times took #{$mars_load_time} seconds."
|
113
|
+
puts ">>> Ox is %0.1f faster than Marshal loading.\n\n" % [$mars_load_time/$ox_load_time]
|
114
|
+
end
|
115
|
+
|
116
|
+
def perf_dump(d)
|
117
|
+
obj = d[:obj]
|
118
|
+
|
119
|
+
start = Time.now
|
120
|
+
(1..$iter).each do
|
121
|
+
xml = Ox.dump(obj, :indent => $indent, :circular => $circular)
|
122
|
+
#puts "*** ox:\n#{xml}"
|
123
|
+
end
|
124
|
+
$ox_dump_time = Time.now - start
|
125
|
+
puts "Ox dumping #{$iter} times with ox took #{$ox_dump_time} seconds."
|
126
|
+
|
127
|
+
Oj.default_options = {:indent => $indent}
|
128
|
+
start = Time.now
|
129
|
+
(1..$iter).each do
|
130
|
+
json = Oj.dump(obj)
|
131
|
+
end
|
132
|
+
$oj_dump_time = Time.now - start
|
133
|
+
puts "Oj dumping #{$iter} times with oj took #{$oj_dump_time} seconds."
|
134
|
+
|
135
|
+
obj = d[:obj]
|
136
|
+
start = Time.now
|
137
|
+
(1..$iter).each do
|
138
|
+
m = Marshal.dump(obj)
|
139
|
+
end
|
140
|
+
$mars_dump_time = Time.now - start
|
141
|
+
puts "Marshal dumping #{$iter} times took #{$mars_dump_time} seconds."
|
142
|
+
puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [$mars_dump_time/$ox_dump_time]
|
143
|
+
end
|
144
|
+
|
145
|
+
def perf_read(d)
|
146
|
+
ox_read_time = 0
|
147
|
+
mars_read_time = 0
|
148
|
+
|
149
|
+
filename = d[:file]
|
150
|
+
marshal_filename = 'sample.marshal'
|
151
|
+
xml = d[:xml]
|
152
|
+
mars = d[:marshal]
|
153
|
+
|
154
|
+
# now load from the file
|
155
|
+
start = Time.now
|
156
|
+
(1..$iter).each do
|
157
|
+
obj = Ox.load_file(filename, :mode => :object)
|
158
|
+
end
|
159
|
+
ox_read_time = Time.now - start
|
160
|
+
puts "Loading and parsing #{$iter} times with ox took #{ox_read_time} seconds."
|
161
|
+
|
162
|
+
start = Time.now
|
163
|
+
(1..$iter).each do
|
164
|
+
m = File.read(marshal_filename)
|
165
|
+
obj = Marshal.load(m)
|
166
|
+
end
|
167
|
+
mars_read_time = Time.now - start
|
168
|
+
puts "Reading and marshalling #{$iter} times took #{mars_read_time} seconds."
|
169
|
+
puts ">>> Ox is %0.1f faster than Marshal loading and parsing.\n\n" % [mars_read_time/ox_read_time]
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
def perf_write(d)
|
174
|
+
ox_write_time = 0
|
175
|
+
mars_write_time = 0
|
176
|
+
|
177
|
+
ox_filename = 'out.xml'
|
178
|
+
marshal_filename = 'out.marshal'
|
179
|
+
obj = d[:obj]
|
180
|
+
|
181
|
+
start = Time.now
|
182
|
+
(1..$iter).each do
|
183
|
+
xml = Ox.to_file(ox_filename, obj, :indent => $indent)
|
184
|
+
end
|
185
|
+
ox_write_time = Time.now - start
|
186
|
+
puts "Ox dumping #{$iter} times with ox took #{ox_write_time} seconds."
|
187
|
+
|
188
|
+
start = Time.now
|
189
|
+
(1..$iter).each do
|
190
|
+
m = Marshal.dump(obj, circular: $circular)
|
191
|
+
File.open(marshal_filename, "w") { |f| f.write(m) }
|
192
|
+
end
|
193
|
+
mars_write_time = Time.now - start
|
194
|
+
puts "Marshal dumping and writing #{$iter} times took #{mars_write_time} seconds."
|
195
|
+
puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [mars_write_time/ox_write_time]
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
#if do_sample or do_files
|
200
|
+
data.each do |d|
|
201
|
+
puts "Using file #{d[:file]}."
|
202
|
+
|
203
|
+
perf_load(d) if do_load
|
204
|
+
perf_dump(d) if do_dump
|
205
|
+
if do_load and do_dump
|
206
|
+
puts ">>> Ox is %0.1f faster than Marshal dumping and loading.\n\n" % [($mars_load_time + $mars_dump_time)/($ox_load_time + $ox_dump_time)] unless 0 == $mars_load_time
|
207
|
+
end
|
208
|
+
|
209
|
+
perf_read(d) if do_read
|
210
|
+
perf_write(d) if do_write
|
211
|
+
|
212
|
+
end
|
213
|
+
#end
|
data/test/test_object.rb
CHANGED
@@ -416,7 +416,7 @@ class ObjectJuice < ::Test::Unit::TestCase
|
|
416
416
|
end
|
417
417
|
|
418
418
|
def test_odd_string
|
419
|
-
Oj.register_odd(Strung, :create, :to_s, 'safe?')
|
419
|
+
Oj.register_odd(Strung, Strung, :create, :to_s, 'safe?')
|
420
420
|
s = Strung.new("Pete", true)
|
421
421
|
dump_and_load(Strung.new("Pete", true), false)
|
422
422
|
end
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.1
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Peter Ohler
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
12
|
+
date: 2014-04-22 00:00:00.000000000 Z
|
12
13
|
dependencies: []
|
13
|
-
description: 'The fastest JSON parser and object serializer. '
|
14
|
+
description: ! 'The fastest JSON parser and object serializer. '
|
14
15
|
email: peter@ohler.com
|
15
16
|
executables: []
|
16
17
|
extensions:
|
@@ -18,61 +19,55 @@ extensions:
|
|
18
19
|
extra_rdoc_files:
|
19
20
|
- README.md
|
20
21
|
files:
|
21
|
-
-
|
22
|
-
-
|
22
|
+
- lib/oj/bag.rb
|
23
|
+
- lib/oj/error.rb
|
24
|
+
- lib/oj/mimic.rb
|
25
|
+
- lib/oj/saj.rb
|
26
|
+
- lib/oj/schandler.rb
|
27
|
+
- lib/oj/version.rb
|
28
|
+
- lib/oj.rb
|
29
|
+
- ext/oj/extconf.rb
|
23
30
|
- ext/oj/buf.h
|
24
|
-
- ext/oj/cache8.c
|
25
31
|
- ext/oj/cache8.h
|
26
|
-
- ext/oj/circarray.c
|
27
32
|
- ext/oj/circarray.h
|
33
|
+
- ext/oj/encode.h
|
34
|
+
- ext/oj/err.h
|
35
|
+
- ext/oj/hash.h
|
36
|
+
- ext/oj/odd.h
|
37
|
+
- ext/oj/oj.h
|
38
|
+
- ext/oj/parse.h
|
39
|
+
- ext/oj/resolve.h
|
40
|
+
- ext/oj/val_stack.h
|
41
|
+
- ext/oj/cache8.c
|
42
|
+
- ext/oj/circarray.c
|
28
43
|
- ext/oj/compat.c
|
29
44
|
- ext/oj/dump.c
|
30
|
-
- ext/oj/encode.h
|
31
45
|
- ext/oj/err.c
|
32
|
-
- ext/oj/err.h
|
33
|
-
- ext/oj/extconf.rb
|
34
46
|
- ext/oj/fast.c
|
35
47
|
- ext/oj/hash.c
|
36
|
-
- ext/oj/hash.h
|
37
48
|
- ext/oj/hash_test.c
|
38
49
|
- ext/oj/object.c
|
39
50
|
- ext/oj/odd.c
|
40
|
-
- ext/oj/odd.h
|
41
51
|
- ext/oj/oj.c
|
42
|
-
- ext/oj/oj.h
|
43
52
|
- ext/oj/parse.c
|
44
|
-
- ext/oj/parse.h
|
45
53
|
- ext/oj/resolve.c
|
46
|
-
- ext/oj/resolve.h
|
47
54
|
- ext/oj/saj.c
|
48
55
|
- ext/oj/scp.c
|
49
56
|
- ext/oj/strict.c
|
50
57
|
- ext/oj/val_stack.c
|
51
|
-
- ext/oj/val_stack.h
|
52
|
-
- lib/oj.rb
|
53
|
-
- lib/oj/bag.rb
|
54
|
-
- lib/oj/error.rb
|
55
|
-
- lib/oj/mimic.rb
|
56
|
-
- lib/oj/saj.rb
|
57
|
-
- lib/oj/schandler.rb
|
58
|
-
- lib/oj/version.rb
|
59
|
-
- test/a.rb
|
60
|
-
- test/bug.rb
|
61
58
|
- test/debian_test.rb
|
62
|
-
- test/e.rb
|
63
59
|
- test/files.rb
|
64
|
-
- test/foo.rb
|
65
|
-
- test/lots.rb
|
66
|
-
- test/mj.rb
|
67
60
|
- test/perf.rb
|
61
|
+
- test/perf1.rb
|
62
|
+
- test/perf2.rb
|
68
63
|
- test/perf_compat.rb
|
69
64
|
- test/perf_fast.rb
|
65
|
+
- test/perf_obj_old.rb
|
70
66
|
- test/perf_object.rb
|
71
67
|
- test/perf_saj.rb
|
72
68
|
- test/perf_scp.rb
|
73
69
|
- test/perf_simple.rb
|
74
70
|
- test/perf_strict.rb
|
75
|
-
- test/sample.rb
|
76
71
|
- test/sample/change.rb
|
77
72
|
- test/sample/dir.rb
|
78
73
|
- test/sample/doc.rb
|
@@ -85,8 +80,8 @@ files:
|
|
85
80
|
- test/sample/rect.rb
|
86
81
|
- test/sample/shape.rb
|
87
82
|
- test/sample/text.rb
|
83
|
+
- test/sample.rb
|
88
84
|
- test/sample_json.rb
|
89
|
-
- test/struct.rb
|
90
85
|
- test/test_compat.rb
|
91
86
|
- test/test_fast.rb
|
92
87
|
- test/test_gc.rb
|
@@ -98,34 +93,36 @@ files:
|
|
98
93
|
- test/test_strict.rb
|
99
94
|
- test/test_writer.rb
|
100
95
|
- test/tests.rb
|
101
|
-
-
|
96
|
+
- LICENSE
|
97
|
+
- README.md
|
102
98
|
homepage: http://www.ohler.com/oj
|
103
99
|
licenses:
|
104
100
|
- MIT
|
105
101
|
- GPL-3.0
|
106
|
-
metadata: {}
|
107
102
|
post_install_message:
|
108
103
|
rdoc_options:
|
109
|
-
-
|
104
|
+
- --main
|
110
105
|
- README.md
|
111
106
|
require_paths:
|
112
107
|
- lib
|
113
108
|
- ext
|
114
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
115
111
|
requirements:
|
116
|
-
- -
|
112
|
+
- - ! '>='
|
117
113
|
- !ruby/object:Gem::Version
|
118
114
|
version: '0'
|
119
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
120
117
|
requirements:
|
121
|
-
- -
|
118
|
+
- - ! '>='
|
122
119
|
- !ruby/object:Gem::Version
|
123
120
|
version: '0'
|
124
121
|
requirements: []
|
125
122
|
rubyforge_project: oj
|
126
|
-
rubygems_version:
|
123
|
+
rubygems_version: 1.8.23
|
127
124
|
signing_key:
|
128
|
-
specification_version:
|
125
|
+
specification_version: 3
|
129
126
|
summary: A fast JSON parser and serializer.
|
130
127
|
test_files: []
|
131
128
|
has_rdoc: true
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 44d745373ae1530f6a0ae6ec981b62c84eac8f2d
|
4
|
-
data.tar.gz: c5c3c1506daf7f2ea35185d67fe1d469ced94fda
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: ef8a3aee09c48dce3f3a8565b1f4412c3703c3c9aad396f08573fc978631ea364dd58d2bd684960b29ec2dfd2b989ea3145f93a994c75b2c1eb0d8a9e5ed1620
|
7
|
-
data.tar.gz: 95429819075ae22192b957da153ea1768eab8e93441e74e988daa4f994d7723e6947d8d6d341f05a3253717c08a3e800d7bd4b770e39ffc702028faf57b96025
|
data/test/a.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -wW1
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.dirname(__FILE__)
|
5
|
-
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
-
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
-
|
8
|
-
require 'pp'
|
9
|
-
require 'oj'
|
10
|
-
require 'perf'
|
11
|
-
|
12
|
-
obj = [[1],[2],[3],[4],[5],[6],[7],[8],[9]]
|
13
|
-
obj = [[],[],[],[],[],[],[],[],[]]
|
14
|
-
obj = {
|
15
|
-
'a' => 'Alpha', # string
|
16
|
-
'b' => true, # boolean
|
17
|
-
'c' => 12345, # number
|
18
|
-
'd' => [ true, [false, [12345, nil], 3.967, ['something', false], nil]], # mix it up array
|
19
|
-
'e' => { 'one' => 1, 'two' => 2 }, # hash
|
20
|
-
'f' => nil, # nil
|
21
|
-
'g' => 12345678901234567890123456789, # big number
|
22
|
-
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
23
|
-
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
24
|
-
}
|
25
|
-
|
26
|
-
json = Oj.dump(obj, mode: :compat)
|
27
|
-
|
28
|
-
puts json
|
29
|
-
#pp Oj.saj_parse(nil, json)
|
30
|
-
pp Oj.t_parse(json)
|
31
|
-
|
32
|
-
if true
|
33
|
-
perf = Perf.new()
|
34
|
-
perf.add('SAJ', 'oj') { Oj.saj_parse(nil, json) }
|
35
|
-
perf.add('T', 'oj') { Oj.t_parse(json) }
|
36
|
-
perf.add('load', 'oj') { Oj.load(json) }
|
37
|
-
perf.run(10000)
|
38
|
-
end
|
data/test/bug.rb
DELETED
@@ -1,17 +0,0 @@
|
|
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
|
-
obj = Oj.load_file('bug.json', :mode => :object)
|
16
|
-
|
17
|
-
puts Oj.dump(obj, :mode => :object, :indent => 0)
|
data/test/e.rb
DELETED
data/test/foo.rb
DELETED
@@ -1,24 +0,0 @@
|
|
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
|
-
reltypes={}
|
16
|
-
Oj::Doc.open_file('foo.json') do |doc|
|
17
|
-
doc.each_child do |target|
|
18
|
-
puts "#{target.local_key} is #{target.local_key.class}"
|
19
|
-
target.each_leaf do |score|
|
20
|
-
reltype=score.local_key
|
21
|
-
reltypes[reltype] = (reltypes[reltype] || 0) + 1
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/test/lots.rb
DELETED
@@ -1,68 +0,0 @@
|
|
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
|
-
module One
|
16
|
-
module Two
|
17
|
-
module Three
|
18
|
-
class Empty
|
19
|
-
|
20
|
-
def initialize()
|
21
|
-
end
|
22
|
-
|
23
|
-
def eql?(o)
|
24
|
-
self.class == o.class
|
25
|
-
end
|
26
|
-
alias == eql?
|
27
|
-
|
28
|
-
def to_hash()
|
29
|
-
{'json_class' => "#{self.class.name}"}
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_json(*a)
|
33
|
-
%{{"json_class":"#{self.class.name}"}}
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.json_create(h)
|
37
|
-
self.new()
|
38
|
-
end
|
39
|
-
end # Empty
|
40
|
-
end # Three
|
41
|
-
end # Two
|
42
|
-
end # One
|
43
|
-
|
44
|
-
$obj = {
|
45
|
-
'a' => 'Alpha', # string
|
46
|
-
'b' => true, # boolean
|
47
|
-
'c' => 12345, # number
|
48
|
-
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
49
|
-
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
50
|
-
'f' => nil, # nil
|
51
|
-
'g' => One::Two::Three::Empty.new(),
|
52
|
-
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
53
|
-
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
54
|
-
}
|
55
|
-
|
56
|
-
$obj = [$obj]*10000
|
57
|
-
|
58
|
-
Oj.default_options = { :indent => 2, :mode => :compat }
|
59
|
-
|
60
|
-
$json = Oj.dump($obj, :mode => :compat)
|
61
|
-
|
62
|
-
$result = nil
|
63
|
-
100.times { |i|
|
64
|
-
print(".") if (0 == i % 10)
|
65
|
-
$result = Oj.compat_load($json)
|
66
|
-
}
|
67
|
-
|
68
|
-
|
data/test/mj.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
-
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
-
# $: << File.join(File.dirname(__FILE__), "../../multi_json/lib")
|
7
|
-
|
8
|
-
require 'multi_json'
|
9
|
-
require 'benchmark'
|
10
|
-
require 'yajl'
|
11
|
-
require 'json'
|
12
|
-
require 'oj'
|
13
|
-
|
14
|
-
iter = 1_000_000
|
15
|
-
iter = 100_000
|
16
|
-
|
17
|
-
json = %({"k1":"val1","k2":"val2","k3":"val3"})
|
18
|
-
obj = { k1: "val1", k2: "val2", k3: "val3" }
|
19
|
-
|
20
|
-
puts "Benchmarks for different JSON handlers with MultiJson."
|
21
|
-
puts " Ruby #{RUBY_VERSION}"
|
22
|
-
puts " #{iter} iterations"
|
23
|
-
|
24
|
-
MultiJson.engine = :oj
|
25
|
-
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
26
|
-
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
27
|
-
puts " Oj decode: #{dt} encode: #{et}"
|
28
|
-
|
29
|
-
MultiJson.engine = :yajl
|
30
|
-
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
31
|
-
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
32
|
-
puts " Yajl decode: #{dt} encode: #{et}"
|
33
|
-
|
34
|
-
MultiJson.engine = :json_gem
|
35
|
-
dt = Benchmark.realtime { iter.times { MultiJson.decode(json) }}
|
36
|
-
et = Benchmark.realtime { iter.times { MultiJson.encode(obj) }}
|
37
|
-
puts " Json decode: #{dt} encode: #{et}"
|
38
|
-
|
39
|
-
Oj.default_options = { :mode => :compat, :time_format => :ruby }
|
40
|
-
dt = Benchmark.realtime { iter.times { Oj.load(json) }}
|
41
|
-
et = Benchmark.realtime { iter.times { Oj.dump(obj) }}
|
42
|
-
puts "Raw Oj decode: #{dt} encode: #{et}"
|
43
|
-
|
44
|
-
ye = Yajl::Encoder.new
|
45
|
-
dt = Benchmark.realtime { iter.times { Yajl::Parser.parse(json) }}
|
46
|
-
et = Benchmark.realtime { iter.times { Yajl::Encoder.encode(obj) }}
|
47
|
-
e2 = Benchmark.realtime { iter.times { ye.encode(obj) }}
|
48
|
-
puts "Raw Yajl decode: #{dt} encode: #{et}, encoder: #{e2}"
|
data/test/struct.rb
DELETED
@@ -1,29 +0,0 @@
|
|
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/x.rb
DELETED
@@ -1,59 +0,0 @@
|
|
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
|
-
# Oj is not able to deserialize all classes that are a subclass of a Ruby
|
16
|
-
# Exception. Only exception that take one required string argument in the
|
17
|
-
# initialize() method are supported. This is an example of how to write an
|
18
|
-
# Exception subclass that supports both a single string intializer and an
|
19
|
-
# Exception as an argument. Additional optional arguments can be added as well.
|
20
|
-
#
|
21
|
-
# The reason for this restriction has to do with a design decision on the part
|
22
|
-
# of the Ruby developers. Exceptions are special Objects. They do not follow the
|
23
|
-
# rules of other Objects. Exceptions have 'mesg' and a 'bt' attribute. Note that
|
24
|
-
# these are not '@mesg' and '@bt'. They can not be set using the normal C or
|
25
|
-
# Ruby calls. The only way I have found to set the 'mesg' attribute is through
|
26
|
-
# the initializer. Unfortunately that means any subclass that provides a
|
27
|
-
# different initializer can not be automatically decoded. A way around this is
|
28
|
-
# to use a create function but this example shows an alternative.
|
29
|
-
|
30
|
-
class WrapException < StandardError
|
31
|
-
attr_reader :original
|
32
|
-
|
33
|
-
def initialize(msg_or_err)
|
34
|
-
if msg_or_err.is_a?(Exception)
|
35
|
-
super(msg_or_err.message)
|
36
|
-
@original = msg_or_err
|
37
|
-
set_backtrace(msg_or_err.backtrace)
|
38
|
-
else
|
39
|
-
super(message)
|
40
|
-
@original = nil
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
e = WrapException.new(RuntimeError.new("Something broke."))
|
46
|
-
|
47
|
-
json = Oj.dump(e, :mode => :object)
|
48
|
-
puts "original:\n#{json}"
|
49
|
-
# outputs:
|
50
|
-
# original:
|
51
|
-
# {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
52
|
-
|
53
|
-
e2 = Oj.load(json, :mode => :object)
|
54
|
-
puts "dumped, loaded, and dumped again:\n#{Oj.dump(e2, :mode => :object)}"
|
55
|
-
# outputs:
|
56
|
-
# original: {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
57
|
-
# dumped, loaded, and dumped again:
|
58
|
-
# {"^o":"WrapException","original":{"^o":"RuntimeError","~mesg":"Something broke.","~bt":null},"~mesg":"Something broke.","~bt":null}
|
59
|
-
|