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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92a7b7be45175f18661ed207bb79b4a03192c731
4
- data.tar.gz: 2c2f13ed34b8d715265c4e9a5a53ee203ed042c1
3
+ metadata.gz: 1b53b303c6deecb0860b8b962cb5e8bdc37c0c80
4
+ data.tar.gz: ece33a05b8cd4f63b323cbf34dfb3a3bad67dd24
5
5
  SHA512:
6
- metadata.gz: 6f195c7904b2c9de392d93e097155dbd32e028a8d0d4bf1640782e16e25aee11dbeaa73c35d1cc472804e378aeab801961c095a0501f1c6c1d976855e89ebfb0
7
- data.tar.gz: ce8fadea6f3f07de21144e16f0b2b1aabeb108debbc34ee6b2b7adb22e9eaca18824b9e354dcf04c1affcd0a2610886ecd3a87b4c4dd0c42557e999f5a914fc8
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.3
29
+ ## Current Release 2.11.4
30
30
 
31
- - DateTime encoding now includes nanoseconds.
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
 
@@ -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
- double secs = NUM2DBL(rb_funcall(rfrac, to_f_id, 0));
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
- secs *= 86400.0;
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;
@@ -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
  */
@@ -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
  }
@@ -229,7 +229,7 @@ read_from_fd(Reader reader) {
229
229
  size_t max = reader->end - reader->tail;
230
230
 
231
231
  cnt = read(reader->fd, reader->tail, max);
232
- if (cnt < 0) {
232
+ if (cnt <= 0) {
233
233
  return -1;
234
234
  } else if (0 != cnt) {
235
235
  reader->read_end = reader->tail + cnt;
@@ -486,7 +486,9 @@ read_num(ParseInfo pi) {
486
486
  }
487
487
  ni.dec_cnt -= zero_cnt;
488
488
  ni.len = pi->rd.tail - pi->rd.str;
489
- reader_backup(&pi->rd);
489
+ if (0 != c) {
490
+ reader_backup(&pi->rd);
491
+ }
490
492
  }
491
493
  if (BigDec == pi->options.bigdec_load) {
492
494
  ni.big = 1;
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.11.3'
4
+ VERSION = '2.11.4'
5
5
  end
@@ -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
- class Handler
11
- def initialize
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
- def array_end
35
- @state.pop
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
- def array_append(a,v)
39
- a << v
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
- def add_value(v)
43
- p v
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) }
@@ -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
@@ -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
@@ -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
@@ -474,6 +474,7 @@ class ObjectJuice < Minitest::Test
474
474
  end
475
475
 
476
476
  def test_odd_datetime
477
+ dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(4, 3)), false)
477
478
  dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(7123456789, 1000000000)), false)
478
479
  end
479
480
 
@@ -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
- Thread.new do
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)
@@ -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.3
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-18 00:00:00.000000000 Z
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/struct.rb
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
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #!/usr/bin/env ruby
4
- # encoding: UTF-8
5
-
6
- $: << File.dirname(__FILE__)
7
-
8
- require 'helper'
9
-
10
-
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]'))
@@ -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
@@ -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
@@ -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
-
@@ -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