oj 2.11.3 → 2.11.4
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 +4 -4
- data/README.md +5 -2
- data/ext/oj/odd.c +13 -9
- data/ext/oj/oj.c +20 -0
- data/ext/oj/parse.c +1 -3
- data/ext/oj/reader.c +1 -1
- data/ext/oj/sparse.c +3 -1
- data/lib/oj/version.rb +1 -1
- data/test/bug.rb +51 -40
- data/test/perf1.rb +64 -0
- data/test/perf2.rb +76 -0
- data/test/perf_obj_old.rb +213 -0
- data/test/test_bigd.rb +63 -0
- data/test/test_object.rb +1 -0
- data/test/{mod.rb → test_range.rb} +9 -6
- data/test/test_various.rb +11 -0
- metadata +7 -9
- data/test/bug2.rb +0 -10
- data/test/io.rb +0 -48
- data/test/struct.rb +0 -29
- data/test/test_serializer.rb +0 -59
- data/test/write_timebars.rb +0 -31
- data/test/zip.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b53b303c6deecb0860b8b962cb5e8bdc37c0c80
|
4
|
+
data.tar.gz: ece33a05b8cd4f63b323cbf34dfb3a3bad67dd24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95e7432d06edccdc616488728fb49bfd65393cf3451fe40b869de89397e0820ab64f8f5d1b252ac435d86798efdbd057fece5877655a6f97e66890d1f676ce2e
|
7
|
+
data.tar.gz: 6edd99edb2d3160a221c168ce30d5779cbec202908c91135c763f57df2024e6a758b6f2ff6f40bfe0ae7c68937accab77af260b951266a9b2021e00096fbf8a8
|
data/README.md
CHANGED
@@ -26,9 +26,12 @@ 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.11.
|
29
|
+
## Current Release 2.11.4
|
30
30
|
|
31
|
-
- DateTime encoding now
|
31
|
+
- DateTime second encoding is now always a Rational to preserve accuracy.
|
32
|
+
|
33
|
+
- Fixed buf in the Oj.load() callback feature that caused an endless loop when
|
34
|
+
a StringIO was used with a JSON that was a number.
|
32
35
|
|
33
36
|
[Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
|
34
37
|
|
data/ext/oj/odd.c
CHANGED
@@ -38,7 +38,10 @@ static long odd_cnt = 0;
|
|
38
38
|
static ID sec_id;
|
39
39
|
static ID sec_fraction_id;
|
40
40
|
static ID to_f_id;
|
41
|
+
static ID numerator_id;
|
42
|
+
static ID denominator_id;
|
41
43
|
static ID rational_id;
|
44
|
+
static VALUE rational_class;
|
42
45
|
|
43
46
|
static void
|
44
47
|
set_class(Odd odd, const char *classname) {
|
@@ -60,18 +63,16 @@ static VALUE
|
|
60
63
|
get_datetime_secs(VALUE obj) {
|
61
64
|
VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
62
65
|
VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
63
|
-
|
66
|
+
long sec = NUM2LONG(rsecs);
|
67
|
+
long num = NUM2LONG(rb_funcall(rfrac, numerator_id, 0));
|
68
|
+
long den = NUM2LONG(rb_funcall(rfrac, denominator_id, 0));
|
64
69
|
|
65
70
|
#if DATETIME_1_8
|
66
|
-
|
67
|
-
#endif
|
68
|
-
secs += NUM2DBL(rb_funcall(rsecs, to_f_id, 0));
|
69
|
-
|
70
|
-
#if DATETIME_1_8
|
71
|
-
return rb_funcall(rb_cObject, rational_id, 2, LONG2FIX((long)(secs * 1000000000)), LONG2FIX(1000000000));
|
72
|
-
#else
|
73
|
-
return rb_float_new(secs);
|
71
|
+
num *= 86400;
|
74
72
|
#endif
|
73
|
+
num += sec * den;
|
74
|
+
|
75
|
+
return rb_funcall(rb_cObject, rational_id, 2, LONG2FIX(num), LONG2FIX(den));
|
75
76
|
}
|
76
77
|
|
77
78
|
void
|
@@ -82,7 +83,10 @@ oj_odd_init() {
|
|
82
83
|
sec_id = rb_intern("sec");
|
83
84
|
sec_fraction_id = rb_intern("sec_fraction");
|
84
85
|
to_f_id = rb_intern("to_f");
|
86
|
+
numerator_id = rb_intern("numerator");
|
87
|
+
denominator_id = rb_intern("denominator");
|
85
88
|
rational_id = rb_intern("Rational");
|
89
|
+
rational_class = rb_const_get(rb_cObject, rational_id);
|
86
90
|
|
87
91
|
memset(_odds, 0, sizeof(_odds));
|
88
92
|
odd = odds;
|
data/ext/oj/oj.c
CHANGED
@@ -608,6 +608,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
608
608
|
* valid. If the input is not a valid JSON document (an empty string is not a
|
609
609
|
* valid JSON document) an exception is raised.
|
610
610
|
*
|
611
|
+
* A block can also be provided with a single argument. That argument will be
|
612
|
+
* the parsed JSON document. This is useful when parsing a string that includes
|
613
|
+
* multiple JSON documents.
|
614
|
+
*
|
611
615
|
* @param [String|IO] json JSON String or an Object that responds to read()
|
612
616
|
* @param [Hash] options load options (same as default_options)
|
613
617
|
*/
|
@@ -629,6 +633,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
629
633
|
* valid. If the input is not a valid JSON document (an empty string is not a
|
630
634
|
* valid JSON document) an exception is raised.
|
631
635
|
*
|
636
|
+
* A block can also be provided with a single argument. That argument will be
|
637
|
+
* the parsed JSON document. This is useful when parsing a string that includes
|
638
|
+
* multiple JSON documents.
|
639
|
+
*
|
632
640
|
* @param [String|IO] json JSON String or an Object that responds to read()
|
633
641
|
* @param [Hash] options load options (same as default_options)
|
634
642
|
*/
|
@@ -666,6 +674,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
666
674
|
* different initializer can not be automatically decoded. A way around this is
|
667
675
|
* to use a create function but this example shows an alternative.
|
668
676
|
*
|
677
|
+
* A block can also be provided with a single argument. That argument will be
|
678
|
+
* the parsed JSON document. This is useful when parsing a string that includes
|
679
|
+
* multiple JSON documents.
|
680
|
+
*
|
669
681
|
* @param [String|IO] json JSON String or an Object that responds to read()
|
670
682
|
* @param [Hash] options load options (same as default_options)
|
671
683
|
*/
|
@@ -686,6 +698,10 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
686
698
|
* a file object is passed as the first argument. A stream input will be parsed
|
687
699
|
* using a stream parser but others use the slightly faster string parser.
|
688
700
|
*
|
701
|
+
* A block can also be provided with a single argument. That argument will be
|
702
|
+
* the parsed JSON document. This is useful when parsing a string that includes
|
703
|
+
* multiple JSON documents.
|
704
|
+
*
|
689
705
|
* @param [String|IO] json JSON String or an Object that responds to read()
|
690
706
|
* @param [Hash] options load options (same as default_options)
|
691
707
|
*/
|
@@ -746,6 +762,10 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
746
762
|
* This is a stream based parser which allows a large or huge file to be loaded
|
747
763
|
* without pulling the whole file into memory.
|
748
764
|
*
|
765
|
+
* A block can also be provided with a single argument. That argument will be
|
766
|
+
* the parsed JSON document. This is useful when parsing a string that includes
|
767
|
+
* multiple JSON documents.
|
768
|
+
*
|
749
769
|
* @param [String] path path to a file containing a JSON document
|
750
770
|
* @param [Hash] options load options (same as default_options)
|
751
771
|
*/
|
data/ext/oj/parse.c
CHANGED
@@ -817,7 +817,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
817
817
|
return oj_pi_sparse(argc, argv, pi, 0);
|
818
818
|
} else {
|
819
819
|
rb_raise(rb_eArgError, "strict_parse() expected a String or IO Object.");
|
820
|
-
|
820
|
+
}
|
821
821
|
}
|
822
822
|
if (Yes == pi->options.circular) {
|
823
823
|
pi->circ_array = oj_circ_array_new();
|
@@ -877,7 +877,6 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
877
877
|
if (err_has(&pi->err)) {
|
878
878
|
oj_err_raise(&pi->err);
|
879
879
|
}
|
880
|
-
|
881
880
|
if (pi->options.quirks_mode == No) {
|
882
881
|
switch (rb_type(result)) {
|
883
882
|
case T_NIL:
|
@@ -894,6 +893,5 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
894
893
|
break;
|
895
894
|
}
|
896
895
|
}
|
897
|
-
|
898
896
|
return result;
|
899
897
|
}
|
data/ext/oj/reader.c
CHANGED
data/ext/oj/sparse.c
CHANGED
data/lib/oj/version.rb
CHANGED
data/test/bug.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
1
|
#!/usr/bin/env ruby
|
4
2
|
# encoding: UTF-8
|
5
3
|
|
@@ -7,47 +5,60 @@ $: << File.dirname(__FILE__)
|
|
7
5
|
|
8
6
|
require 'helper'
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
@state = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def hash_start
|
16
|
-
@state << {}
|
17
|
-
@state.last
|
18
|
-
end
|
19
|
-
|
20
|
-
def hash_end
|
21
|
-
@state.pop
|
22
|
-
end
|
23
|
-
|
24
|
-
def hash_set(h,k,v)
|
25
|
-
h.store(k,v)
|
26
|
-
end
|
27
|
-
|
28
|
-
def array_start
|
29
|
-
@state << []
|
30
|
-
@state.last
|
31
|
-
end
|
32
|
-
|
8
|
+
require 'oj'
|
9
|
+
require 'securerandom'
|
33
10
|
|
34
|
-
|
35
|
-
|
11
|
+
class Handler
|
12
|
+
def hash_start() {} end
|
13
|
+
def hash_set(h,k,v) h.store(k,v) end
|
14
|
+
def array_start() [] end
|
15
|
+
def array_append(a,v) a << v end
|
16
|
+
def error(message, line, column)
|
17
|
+
raise Exception.new(message, line, column)
|
36
18
|
end
|
19
|
+
end
|
37
20
|
|
38
|
-
|
39
|
-
|
21
|
+
json = Oj.dump({"this"=>"object"})
|
22
|
+
|
23
|
+
if true
|
24
|
+
name = "/tmp/#{SecureRandom.uuid}"
|
25
|
+
`mkfifo #{name}`
|
26
|
+
if fork
|
27
|
+
open(name, 'r+') do |read_io|
|
28
|
+
p "start reading #{read_io.stat.ftype}"
|
29
|
+
Oj.sc_parse(Handler.new, read_io) {|v| p v}
|
30
|
+
p "stop reading"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
open(name, 'w+') do |write_io|
|
34
|
+
p "start writing #{write_io.stat.ftype} autoclose: #{write_io.autoclose?}"
|
35
|
+
write_io.write json
|
36
|
+
write_io.write json
|
37
|
+
p "stop writing"
|
38
|
+
end
|
39
|
+
sleep(1) # make it obvious that there are two threads
|
40
|
+
open(name, 'w+') do |write_io|
|
41
|
+
p "start writing #{write_io.stat.ftype}"
|
42
|
+
write_io.write json
|
43
|
+
write_io.write json
|
44
|
+
p "stop writing"
|
45
|
+
end
|
40
46
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
47
|
+
else
|
48
|
+
IO.pipe do |read_io, write_io|
|
49
|
+
if fork
|
50
|
+
write_io.close
|
51
|
+
p "start reading #{read_io.stat.ftype}"
|
52
|
+
Oj.sc_parse(Handler.new, read_io) {|v| p v}
|
53
|
+
p "stop reading"
|
54
|
+
read_io.close
|
55
|
+
else
|
56
|
+
read_io.close
|
57
|
+
p "start writing #{write_io.stat.ftype}"
|
58
|
+
write_io.write json
|
59
|
+
write_io.write json
|
60
|
+
p "stop writing"
|
61
|
+
write_io.close
|
62
|
+
end
|
44
63
|
end
|
45
|
-
|
46
|
-
def error(message, line, column); p "ERROR: #{message}" end
|
47
64
|
end
|
48
|
-
|
49
|
-
$handler = Handler.new
|
50
|
-
|
51
|
-
IO.popen("cat tst") { |p| puts Oj.sc_parse($handler, p) }
|
52
|
-
|
53
|
-
#File.open('tst', 'r') { |file| Oj.sc_parse($handler, file) }
|
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_bigd.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$VERBOSE = true
|
5
|
+
|
6
|
+
%w(lib ext test).each do |dir|
|
7
|
+
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rubygems' if RUBY_VERSION.start_with?('1.8.')
|
11
|
+
|
12
|
+
#require "minitest/spec"
|
13
|
+
require "minitest/autorun"
|
14
|
+
|
15
|
+
require "oj"
|
16
|
+
|
17
|
+
# Uncomment this line and test_big_decimal will fail
|
18
|
+
require "active_support/json"
|
19
|
+
|
20
|
+
# With ActiveSupport 4.0, neither of these settings affect BigDecimal#to_json,
|
21
|
+
# only BigDecimal#as_json
|
22
|
+
#
|
23
|
+
# ActiveSupport.encode_big_decimal_as_string = false
|
24
|
+
# ActiveSupport::JSON::Encoding.encode_big_decimal_as_string = false
|
25
|
+
|
26
|
+
describe Oj do
|
27
|
+
|
28
|
+
# Options set by default in Rails 4.0 / Rabl
|
29
|
+
def options
|
30
|
+
{
|
31
|
+
:bigdecimal_as_decimal=>true, # default = true
|
32
|
+
:use_to_json=>true, # default = false
|
33
|
+
:mode=>:compat, # default = object
|
34
|
+
:time_format=>:ruby, # default = unix
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_big_decimal
|
39
|
+
orig = BigDecimal.new("3.14159265359")
|
40
|
+
puts "*** to_s: #{orig.to_s}"
|
41
|
+
puts "*** to_json: #{orig.to_json}"
|
42
|
+
puts "*** JSON.dump: #{JSON.dump(orig)}"
|
43
|
+
json = Oj.dump(orig, options)
|
44
|
+
puts "*** json: #{json}"
|
45
|
+
|
46
|
+
value = Oj.load(json)
|
47
|
+
puts "*** value: #{value.class}"
|
48
|
+
assert_equal(value, orig)
|
49
|
+
|
50
|
+
# by default, without active support
|
51
|
+
# assert_equal("0.314159265359E1", json)
|
52
|
+
# in Rails 4.1, with active support
|
53
|
+
# assert_equal("3.14159265359", json)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Floats are unaffected
|
57
|
+
def test_float
|
58
|
+
orig = 3.14159265359
|
59
|
+
json = Oj.dump(orig, options)
|
60
|
+
assert_equal("3.14159265359", json)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/test/test_object.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: UTF-8
|
3
3
|
|
4
|
+
$VERBOSE = true
|
5
|
+
|
4
6
|
%w(lib ext test).each do |dir|
|
5
7
|
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
6
8
|
end
|
7
9
|
|
10
|
+
require 'rubygems' if RUBY_VERSION.start_with?('1.8.')
|
8
11
|
require 'oj'
|
9
12
|
|
13
|
+
Oj.mimic_JSON
|
14
|
+
|
15
|
+
#puts Oj.default_options
|
16
|
+
|
17
|
+
range = ("01".."12")
|
10
18
|
|
11
|
-
|
12
|
-
string_io = StringIO.new('{"foo":"bar"}')
|
13
|
-
Oj.load(string_io)
|
14
|
-
string_io.rewind
|
15
|
-
puts string_io.read
|
16
|
-
end.join
|
19
|
+
puts Oj.dump(range)
|
data/test/test_various.rb
CHANGED
@@ -286,6 +286,17 @@ class Juice < Minitest::Test
|
|
286
286
|
assert(false, "*** expected an exception")
|
287
287
|
end
|
288
288
|
|
289
|
+
# multiple JSON in one string
|
290
|
+
def test_multiple_json_callback
|
291
|
+
json = %{{"a":1}
|
292
|
+
[1,2][3,4]
|
293
|
+
{"b":2}
|
294
|
+
}
|
295
|
+
results = []
|
296
|
+
Oj.load(json) { |x| results << x }
|
297
|
+
assert_equal([{"a"=>1}, [1,2], [3,4], {"b"=>2}], results)
|
298
|
+
end
|
299
|
+
|
289
300
|
# encoding tests
|
290
301
|
def test_does_not_escape_entities_by_default
|
291
302
|
Oj.default_options = { :escape_mode => :ascii } # set in mimic mode
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.11.
|
4
|
+
version: 2.11.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -106,10 +106,8 @@ files:
|
|
106
106
|
- test/_test_active_mimic.rb
|
107
107
|
- test/_test_mimic_rails.rb
|
108
108
|
- test/bug.rb
|
109
|
-
- test/bug2.rb
|
110
109
|
- test/files.rb
|
111
110
|
- test/helper.rb
|
112
|
-
- test/io.rb
|
113
111
|
- test/isolated/shared.rb
|
114
112
|
- test/isolated/test_mimic_after.rb
|
115
113
|
- test/isolated/test_mimic_alone.rb
|
@@ -117,11 +115,13 @@ files:
|
|
117
115
|
- test/isolated/test_mimic_define.rb
|
118
116
|
- test/isolated/test_mimic_rails_after.rb
|
119
117
|
- test/isolated/test_mimic_rails_before.rb
|
120
|
-
- test/mod.rb
|
121
118
|
- test/perf.rb
|
119
|
+
- test/perf1.rb
|
120
|
+
- test/perf2.rb
|
122
121
|
- test/perf_compat.rb
|
123
122
|
- test/perf_fast.rb
|
124
123
|
- test/perf_file.rb
|
124
|
+
- test/perf_obj_old.rb
|
125
125
|
- test/perf_object.rb
|
126
126
|
- test/perf_saj.rb
|
127
127
|
- test/perf_scp.rb
|
@@ -141,21 +141,19 @@ files:
|
|
141
141
|
- test/sample/shape.rb
|
142
142
|
- test/sample/text.rb
|
143
143
|
- test/sample_json.rb
|
144
|
-
- test/
|
144
|
+
- test/test_bigd.rb
|
145
145
|
- test/test_compat.rb
|
146
146
|
- test/test_debian.rb
|
147
147
|
- test/test_fast.rb
|
148
148
|
- test/test_file.rb
|
149
149
|
- test/test_gc.rb
|
150
150
|
- test/test_object.rb
|
151
|
+
- test/test_range.rb
|
151
152
|
- test/test_saj.rb
|
152
153
|
- test/test_scp.rb
|
153
|
-
- test/test_serializer.rb
|
154
154
|
- test/test_strict.rb
|
155
155
|
- test/test_various.rb
|
156
156
|
- test/test_writer.rb
|
157
|
-
- test/write_timebars.rb
|
158
|
-
- test/zip.rb
|
159
157
|
homepage: http://www.ohler.com/oj
|
160
158
|
licenses:
|
161
159
|
- MIT
|
data/test/bug2.rb
DELETED
data/test/io.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.dirname(__FILE__)
|
5
|
-
|
6
|
-
require 'helper'
|
7
|
-
|
8
|
-
class Handler
|
9
|
-
def initialize
|
10
|
-
@state = []
|
11
|
-
end
|
12
|
-
|
13
|
-
def hash_start
|
14
|
-
@state << {}
|
15
|
-
@state.last
|
16
|
-
end
|
17
|
-
|
18
|
-
def hash_end
|
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 error(message, line, column); p "ERROR: #{message}" end
|
41
|
-
end
|
42
|
-
|
43
|
-
handler = Handler.new
|
44
|
-
def handler.add_value(v)
|
45
|
-
p v
|
46
|
-
end
|
47
|
-
|
48
|
-
Oj.sc_parse(handler, StringIO.new('{"a":"b","c":[1,2,{"d":"e"}]}[4,5,6]'))
|
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/test_serializer.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.dirname(__FILE__)
|
5
|
-
|
6
|
-
%w(lib ext test).each do |dir|
|
7
|
-
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
8
|
-
end
|
9
|
-
|
10
|
-
require 'minitest'
|
11
|
-
require 'minitest/autorun'
|
12
|
-
require 'oj'
|
13
|
-
|
14
|
-
Oj.mimic_JSON
|
15
|
-
|
16
|
-
require 'rails/all'
|
17
|
-
require 'active_model'
|
18
|
-
require 'active_model_serializers'
|
19
|
-
require 'active_support/json'
|
20
|
-
|
21
|
-
#Oj.mimic_JSON
|
22
|
-
|
23
|
-
class Category
|
24
|
-
include ActiveModel::Model
|
25
|
-
include ActiveModel::SerializerSupport
|
26
|
-
|
27
|
-
attr_accessor :id, :name
|
28
|
-
|
29
|
-
def initialize(id, name)
|
30
|
-
@id = id
|
31
|
-
@name = name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class CategorySerializer < ActiveModel::Serializer
|
36
|
-
attributes :id, :name
|
37
|
-
end
|
38
|
-
|
39
|
-
class MimicRails < Minitest::Test
|
40
|
-
|
41
|
-
def test_dump_object
|
42
|
-
Oj.default_options= {:indent => 0}
|
43
|
-
category = Category.new(1, 'test')
|
44
|
-
serializer = CategorySerializer.new(category)
|
45
|
-
|
46
|
-
json = serializer.to_json()
|
47
|
-
puts "*** serializer.to_json() #{serializer.to_json()}"
|
48
|
-
assert_equal(%|{"category":{"id":1,"name":"test"}}|, json)
|
49
|
-
|
50
|
-
json = serializer.as_json()
|
51
|
-
puts "*** serializer.as_json() #{serializer.as_json()}"
|
52
|
-
assert_equal({"category" => {:id => 1, :name => "test"}}, json)
|
53
|
-
|
54
|
-
json = JSON.dump(serializer)
|
55
|
-
puts "*** JSON.dump(serializer) #{JSON.dump(serializer)}"
|
56
|
-
assert_equal(%|{"category":{"id":1,"name":"test"}}|, json)
|
57
|
-
end
|
58
|
-
|
59
|
-
end # MimicRails
|
data/test/write_timebars.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
%w(lib ext).each do |dir|
|
5
|
-
$LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'stringio'
|
9
|
-
require 'oj'
|
10
|
-
|
11
|
-
|
12
|
-
filename = File.join(File.dirname(__FILE__), 'day.json')
|
13
|
-
File.open(filename, "w") do |f|
|
14
|
-
w = Oj::StreamWriter.new(f, :indent => -1)
|
15
|
-
390.times do |i|
|
16
|
-
w.push_object()
|
17
|
-
w.push_value(12, 'msgType')
|
18
|
-
w.push_value(1, 'version')
|
19
|
-
w.push_value(1_400_074_200 + i * 60, 'bar')
|
20
|
-
w.push_value('TBC', 'source')
|
21
|
-
w.push_array('timebars')
|
22
|
-
w.push_object()
|
23
|
-
w.push_value('aapl_24', 'asset')
|
24
|
-
w.push_value(91.87, 'close')
|
25
|
-
w.pop()
|
26
|
-
w.pop()
|
27
|
-
w.pop()
|
28
|
-
end
|
29
|
-
f.write("\n")
|
30
|
-
end
|
31
|
-
|
data/test/zip.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
$: << File.dirname(__FILE__)
|
5
|
-
|
6
|
-
require 'helper'
|
7
|
-
|
8
|
-
require 'zlib'
|
9
|
-
|
10
|
-
File.open('test.json.gz', 'r') do |file|
|
11
|
-
Zlib::GzipReader.wrap(file) do |f2|
|
12
|
-
puts "*** f2: #{f2}"
|
13
|
-
Oj.load(f2) do |val|
|
14
|
-
puts val
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
=begin
|
20
|
-
And a json file with the following contents (then gzipped):
|
21
|
-
|
22
|
-
{"a":2}
|
23
|
-
{"b":2}
|
24
|
-
The output is:
|
25
|
-
|
26
|
-
{"a"=>2}
|
27
|
-
{"b"=>2}
|
28
|
-
bin/test:8:in `load': undefined method `new' for #<EOFError: end of file reached> (NoMethodError)
|
29
|
-
from bin/test:8:in `block (2 levels) in <main>'
|
30
|
-
from bin/test:7:in `wrap'
|
31
|
-
from bin/test:7:in `block in <main>'
|
32
|
-
from bin/test:6:in `open'
|
33
|
-
from bin/test:6:in `<main>'
|
34
|
-
=end
|