oj 3.10.1 → 3.10.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dd1cae4ccf720f35b777913213b66466c7d9752055c60d828cdf681956731a3
4
- data.tar.gz: e913c57a4619bfbea97144f6f4783219aca294e598c8c6449ddfc6cb997b46f7
3
+ metadata.gz: 21e870cbb9a2f1c2b99efd6522ce9c284828865b922e299232e60abd4e916f7e
4
+ data.tar.gz: d1d93c3d58b7ed858e1a4ea89698861485bbeeb19b01bc66e3e8890ab7d93583
5
5
  SHA512:
6
- metadata.gz: dc0b7bd0e9ea90e69eda6a6205c09540e2217f9ccdcb3c6e937fb82e4b979fada30a028b64559ac5dfddc22afb9d4302669de35315bb5c5392ad100a373bb472
7
- data.tar.gz: 8d8ad9eeb68fb2d058c3f499ad51fc8c50d3349b36a237769f996a43de58449fbae36d3bff82c6be6a16828331f12aa19df6a1ef90b5bdff78ecdf732450a268
6
+ metadata.gz: 7c5d6b2d7a7830b80ecc23436e50b0f42f53e82febe31ceb0168f440e5368ed323c19433894724beea83e7587013170b6a38be92b65b073d9881f8176a8d283b
7
+ data.tar.gz: 1558090a4a1b066418b9f36064c845ab99e423246f26af8aff682e8f09b8cfce29531f6e677c6e4d8b16056406251b2fe54b463e4ddef121adced8c9d3c167b2
@@ -111,7 +111,7 @@ static char rails_friendly_chars[256] = "\
111
111
  11111111111111111111111111111111\
112
112
  11111111111111111111111111111111\
113
113
  11111111111111111111111111111111\
114
- 11611111111111111111111111111111";
114
+ 11111111111111111111111111111111";
115
115
 
116
116
  static void
117
117
  raise_strict(VALUE obj) {
@@ -618,7 +618,7 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
618
618
  vid = rb_to_id(*np);
619
619
  attr = rb_id2name(vid);
620
620
  if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
621
- return ST_CONTINUE;
621
+ continue;
622
622
  }
623
623
  value = rb_ivar_get(obj, vid);
624
624
 
@@ -669,7 +669,8 @@ static void
669
669
  array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
670
670
  volatile VALUE rval = Qnil;
671
671
 
672
- if (3 <= len && 0 != pi->circ_array) {
672
+ // orig lets us know whether the string was ^r1 or \u005er1
673
+ if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
673
674
  if ('i' == str[1]) {
674
675
  long i = read_long(str + 2, len - 2);
675
676
 
@@ -803,7 +803,7 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
803
803
  }
804
804
 
805
805
  /* Document-method: load
806
- * call-seq: load(json, options) { _|_obj, start, len_|_ }
806
+ * call-seq: load(json, options={}) { _|_obj, start, len_|_ }
807
807
  *
808
808
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
809
809
  * Float, true, false, or nil according to the default mode or the mode
@@ -887,7 +887,7 @@ load(int argc, VALUE *argv, VALUE self) {
887
887
  }
888
888
 
889
889
  /* Document-method: load_file
890
- * call-seq: load_file(path, options) { _|_obj, start, len_|_ }
890
+ * call-seq: load_file(path, options={}) { _|_obj, start, len_|_ }
891
891
  *
892
892
  * Parses a JSON document String into a Object, Hash, Array, String, Fixnum,
893
893
  * Float, true, false, or nil according to the default mode or the mode
@@ -1045,7 +1045,7 @@ safe_load(VALUE self, VALUE doc) {
1045
1045
  */
1046
1046
 
1047
1047
  /* Document-method: dump
1048
- * call-seq: dump(obj, options)
1048
+ * call-seq: dump(obj, options={})
1049
1049
  *
1050
1050
  * Dumps an Object (obj) to a string.
1051
1051
  * - *obj* [_Object_] Object to serialize as an JSON document String
@@ -1143,7 +1143,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
1143
1143
  }
1144
1144
 
1145
1145
  /* Document-method: to_file
1146
- * call-seq: to_file(file_path, obj, options)
1146
+ * call-seq: to_file(file_path, obj, options={})
1147
1147
  *
1148
1148
  * Dumps an Object to the specified file.
1149
1149
  * - *file* [_String_] _path file path to write the JSON document to
@@ -1166,7 +1166,7 @@ to_file(int argc, VALUE *argv, VALUE self) {
1166
1166
  }
1167
1167
 
1168
1168
  /* Document-method: to_stream
1169
- * call-seq: to_stream(io, obj, options)
1169
+ * call-seq: to_stream(io, obj, options={})
1170
1170
  *
1171
1171
  * Dumps an Object to the specified IO stream.
1172
1172
  * - *io* [_IO_] IO stream to write the JSON document to
@@ -453,6 +453,7 @@ read_num(ParseInfo pi) {
453
453
  // except when mimicing the JSON gem or in strict mode.
454
454
  if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
455
455
  int pos = (int)(pi->cur - ni.str);
456
+
456
457
  if (1 == pos || (2 == pos && ni.neg)) {
457
458
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
458
459
  return;
@@ -468,11 +469,19 @@ read_num(ParseInfo pi) {
468
469
  if (0 < ni.num || 0 < ni.i) {
469
470
  dec_cnt++;
470
471
  }
471
- ni.num = ni.num * 10 + d;
472
- ni.div *= 10;
473
- ni.di++;
474
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
475
- ni.big = 1;
472
+ if (INT64_MAX <= ni.div) {
473
+ if (!ni.no_big) {
474
+ ni.big = true;
475
+ }
476
+ } else {
477
+ ni.num = ni.num * 10 + d;
478
+ ni.div *= 10;
479
+ ni.di++;
480
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
481
+ if (!ni.no_big) {
482
+ ni.big = true;
483
+ }
484
+ }
476
485
  }
477
486
  }
478
487
  }
@@ -490,7 +499,7 @@ read_num(ParseInfo pi) {
490
499
  for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
491
500
  ni.exp = ni.exp * 10 + (*pi->cur - '0');
492
501
  if (EXP_MAX <= ni.exp) {
493
- ni.big = 1;
502
+ ni.big = true;
494
503
  }
495
504
  }
496
505
  if (eneg) {
@@ -795,13 +804,13 @@ oj_num_as_value(NumInfo ni) {
795
804
  }
796
805
  } else {
797
806
  // All these machinations are to get rounding to work better.
798
- long double d = (long double)ni->i * (long double)ni->div + (long double)ni->num;
807
+ long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
799
808
  int x = (int)((int64_t)ni->exp - ni->di);
800
809
 
801
810
  // Rounding sometimes cuts off the last digit even if there are only
802
811
  // 15 digits. This attempts to fix those few cases where this
803
812
  // occurs.
804
- if ((long double)INT64_MAX > d && (int64_t)d != (ni->i * ni->div + ni->num)) {
813
+ if ((long double)INT64_MAX > ld && (int64_t)ld != (ni->i * ni->div + ni->num)) {
805
814
  volatile VALUE bd = rb_str_new(ni->str, ni->len);
806
815
 
807
816
  rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
@@ -809,16 +818,36 @@ oj_num_as_value(NumInfo ni) {
809
818
  rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
810
819
  }
811
820
  } else {
812
- d = roundl(d);
821
+ double d;
822
+ double d2;
823
+
824
+ ld = roundl(ld);
825
+ // You would expect that staying with a long double would be
826
+ // more accurate but it fails to match what Ruby generates so
827
+ // drop down to a double.
813
828
  if (0 < x) {
814
- d *= powl(10.0L, x);
829
+ d = (double)(ld * powl(10.0, x));
830
+ d2 = (double)ld * pow(10.0, x);
815
831
  } else if (0 > x) {
816
- d /= powl(10.0L, -x);
832
+ d = (double)(ld / powl(10.0, -x));
833
+ d2 = (double)ld / pow(10.0, -x);
834
+ } else {
835
+ d = (double)ld;
836
+ d2 = d;
817
837
  }
818
- if (ni->neg) {
819
- d = -d;
838
+ if (d != d2) {
839
+ volatile VALUE bd = rb_str_new(ni->str, ni->len);
840
+
841
+ rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
842
+ if (ni->no_big) {
843
+ rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
844
+ }
845
+ } else {
846
+ if (ni->neg) {
847
+ d = -d;
848
+ }
849
+ rnum = rb_float_new(d);
820
850
  }
821
- rnum = rb_float_new((double)d);
822
851
  }
823
852
  }
824
853
  }
@@ -841,6 +870,12 @@ oj_set_error_at(ParseInfo pi, VALUE err_clas, const char* file, int line, const
841
870
  if (p + 3 < end) {
842
871
  *p++ = ' ';
843
872
  *p++ = '(';
873
+ *p++ = 'a';
874
+ *p++ = 'f';
875
+ *p++ = 't';
876
+ *p++ = 'e';
877
+ *p++ = 'r';
878
+ *p++ = ' ';
844
879
  start = p;
845
880
  for (vp = pi->stack.head; vp < pi->stack.tail; vp++) {
846
881
  if (end <= p + 1 + vp->klen) {
@@ -1012,7 +1012,6 @@ rails_encode(int argc, VALUE *argv, VALUE self) {
1012
1012
  }
1013
1013
  }
1014
1014
 
1015
- // TBD provide a get function as well
1016
1015
  static VALUE
1017
1016
  rails_use_standard_json_time_format(VALUE self, VALUE state) {
1018
1017
  if (Qtrue == state || Qfalse == state) {
@@ -409,6 +409,7 @@ read_num(ParseInfo pi) {
409
409
  ni.neg = 0;
410
410
  ni.hasExp = 0;
411
411
  ni.no_big = (FloatDec == pi->options.bigdec_load);
412
+
412
413
  c = reader_get(&pi->rd);
413
414
  if ('-' == c) {
414
415
  c = reader_get(&pi->rd);
@@ -469,11 +470,19 @@ read_num(ParseInfo pi) {
469
470
  if (0 < ni.num || 0 < ni.i) {
470
471
  dec_cnt++;
471
472
  }
472
- ni.num = ni.num * 10 + d;
473
- ni.div *= 10;
474
- ni.di++;
475
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
476
- ni.big = 1;
473
+ if (INT64_MAX <= ni.div) {
474
+ if (!ni.no_big) {
475
+ ni.big = true;
476
+ }
477
+ } else {
478
+ ni.num = ni.num * 10 + d;
479
+ ni.div *= 10;
480
+ ni.di++;
481
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
482
+ if (!ni.no_big) {
483
+ ni.big = true;
484
+ }
485
+ }
477
486
  }
478
487
  }
479
488
  }
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.10.1'
4
+ VERSION = '3.10.7'
5
5
  end
@@ -80,16 +80,16 @@ dynamically modifying classes or reloading classes then don't use this.
80
80
 
81
81
  ### :create_additions
82
82
 
83
- A flag indicating the :create_id key when encountered during parsing should
84
- creating an Object mactching the class name specified in the value associated
85
- with the key.
83
+ A flag indicating that the :create_id key, when encountered during parsing,
84
+ should create an Object matching the class name specified in the value
85
+ associated with the key.
86
86
 
87
87
  ### :create_id [String]
88
88
 
89
89
  The :create_id option specifies that key is used for dumping and loading when
90
90
  specifying the class for an encoded object. The default is `json_create`.
91
91
 
92
- In the `:custom` mode setting the `:create_id` to nil will cause Complex,
92
+ In the `:custom` mode, setting the `:create_id` to nil will cause Complex,
93
93
  Rational, Range, and Regexp to be output as strings instead of as JSON
94
94
  objects.
95
95
 
@@ -179,7 +179,7 @@ customization.
179
179
  ### :nan [Symbol]
180
180
 
181
181
  How to dump Infinity, -Infinity, and NaN in :null, :strict, and :compat
182
- mode. Default is :auto but is ignored in the :compat and :rails mode.
182
+ mode. Default is :auto but is ignored in the :compat and :rails modes.
183
183
 
184
184
  - `:null` places a null
185
185
 
@@ -252,7 +252,7 @@ The :time_format when dumping.
252
252
 
253
253
  - `:unix` time is output as a decimal number in seconds since epoch including fractions of a second.
254
254
 
255
- - `:unix_zone` similar to the `:unix` format but with the timezone encoded in
255
+ - `:unix_zone` is similar to the `:unix` format but with the timezone encoded in
256
256
  the exponent of the decimal number of seconds since epoch.
257
257
 
258
258
  - `:xmlschema` time is output as a string that follows the XML schema definition.
@@ -262,16 +262,16 @@ The :time_format when dumping.
262
262
  ### :use_as_json [Boolean]
263
263
 
264
264
  Call `as_json()` methods on dump, default is false. The option is ignored in
265
- the :compat and :rails mode.
265
+ the :compat and :rails modes.
266
266
 
267
267
 
268
268
  ### :use_raw_json [Boolean]
269
269
 
270
270
  Call `raw_json()` methods on dump, default is false. The option is
271
- accepted in the :compat and :rails mode even though it is not
271
+ accepted in the :compat and :rails modes even though it is not
272
272
  supported by other JSON gems. It provides a means to optimize dump or
273
273
  generate performance. The `raw_json(depth, indent)` method should be
274
- called only by Oj. It is not intended for any other use. This is mean
274
+ called only by Oj. It is not intended for any other use. This is meant
275
275
  to replace the abused `to_json` methods. Calling `Oj.dump` inside the
276
276
  `raw_json` with the object itself when `:use_raw_json` is true will
277
277
  result in an infinite loop.
@@ -279,9 +279,9 @@ result in an infinite loop.
279
279
  ### :use_to_hash [Boolean]
280
280
 
281
281
  Call `to_hash()` methods on dump, default is false. The option is ignored in
282
- the :compat and :rails mode.
282
+ the :compat and :rails modes.
283
283
 
284
284
  ### :use_to_json [Boolean]
285
285
 
286
286
  Call `to_json()` methods on dump, default is false. The option is ignored in
287
- the :compat and :rails mode.
287
+ the :compat and :rails modes.
@@ -80,6 +80,45 @@ The classes that can be put in optimized mode and are optimized when
80
80
  The ActiveSupport decoder is the `JSON.parse()` method. Calling the
81
81
  `Oj::Rails.set_decoder()` method replaces that method with the Oj equivalent.
82
82
 
83
+ ### Usage in Rails 3
84
+
85
+ To support Rails 3 you can create a new module mixin to prepend to controllers:
86
+
87
+ ```ruby
88
+ require 'oj'
89
+
90
+ module OjJsonEncoder
91
+ def render(options = nil, extra_options = {}, &block)
92
+ if options && options.is_a?(Hash) && options[:json]
93
+ obj = options.delete(:json)
94
+ obj = Oj.dump(obj, :mode => :rails) unless obj.is_a?(String)
95
+ options[:text] = obj
96
+ response.content_type ||= Mime::JSON
97
+ end
98
+ super
99
+ end
100
+ end
101
+ ```
102
+
103
+ Usage:
104
+
105
+ ```ruby
106
+ class MyController < ApplicationController
107
+ prepend OjJsonEncoder
108
+ def index
109
+ render :json => { :hello => 'world' }
110
+ end
111
+ end
112
+ ```
113
+
114
+ ### Older Ruby Version Support (Pre 2.3.0)
115
+
116
+ If you are using an older version of Ruby, you can pin `oj` to an earlier version in your Gemfile:
117
+
118
+ ```ruby
119
+ gem 'oj', '3.7.12'
120
+ ```
121
+
83
122
  ### Notes:
84
123
 
85
124
  1. Optimized Floats set the significant digits to 16. This is different than
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
3
  $: << File.dirname(__FILE__)
5
4
  $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
@@ -7,16 +6,30 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
7
6
  $: << File.join($oj_dir, dir)
8
7
  end
9
8
 
10
- require 'rails'
11
9
  require 'active_support'
12
- require 'active_support/json'
10
+ require "active_support/json"
13
11
 
14
- require 'oj'
12
+ $s = "\u2014 & \n \u{1F618}"
13
+
14
+ =begin
15
+ def check(label)
16
+ puts "\n--- #{label} --------------------"
17
+
18
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
19
+ puts "with standard_json == true: t.to_json - #{$t.to_json}"
20
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
21
+ puts "with standard_json == false: t.to_json - #{$t.to_json}"
22
+ end
23
+
24
+ check('Before Oj')
25
+ =end
15
26
 
16
- puts Rails::VERSION::STRING
27
+ require 'oj'
17
28
 
18
- #Oj.optimize_rails
29
+ ActiveSupport::JSON::Encoding.escape_html_entities_in_json = false
30
+ puts "ActiveSupport.encode(s) - #{ActiveSupport::JSON.encode($s)}"
19
31
 
20
- h = {foo: "bar"}
32
+ Oj.optimize_rails
33
+ Oj.default_options = { mode: :rails }
21
34
 
22
- puts Oj.dump(h, mode: :rails)
35
+ puts "Oj.dump(s) - #{Oj.dump($s)}"
@@ -15,7 +15,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
15
15
  def setup
16
16
  @hash = {
17
17
  'a' => 2,
18
- 'b' => 3.141,
18
+ 'b' => 5.23683071,
19
19
  'c' => 'c',
20
20
  'd' => [ 1, "b", 3.14 ],
21
21
  'e' => { 'foo' => 'bar' },
@@ -23,7 +23,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
23
23
  'h' => 1000.0,
24
24
  'i' => 0.001
25
25
  }
26
- @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
26
+ @json = '{"a":2,"b":5.23683071,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
27
27
  '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
28
28
  end
29
29
 
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oj'
4
+
5
+ extras = {"locationLng" => -97.14690769100295}
6
+
7
+ Oj.default_options = {float_precision: 17}
8
+
9
+ encoded = Oj.dump(extras)
10
+ puts encoded
11
+ puts Oj.load(encoded)
12
+
13
+ require "active_record"
14
+
15
+ Oj::Rails.set_encoder()
16
+ Oj::Rails.set_decoder()
17
+
18
+ Oj.default_options = {float_precision: 17}
19
+ # Using Oj rails encoder, gets the correct value: {"locationLng":-97.14690769100295}
20
+ encoded = ActiveSupport::JSON.encode(extras)
21
+ puts encoded
22
+ puts ActiveSupport::JSON.decode(encoded)
23
+ puts Oj.load(encoded)
@@ -118,6 +118,11 @@ class CustomJuice < Minitest::Test
118
118
  dump_and_load(-2.48e100 * 1.0e10, false)
119
119
  end
120
120
 
121
+ def test_float_parse
122
+ f = Oj.load("12.123456789012345678", mode: :custom, bigdecimal_load: :float);
123
+ assert_equal(Float, f.class)
124
+ end
125
+
121
126
  def test_nan_dump
122
127
  assert_equal('null', Oj.dump(0/0.0, :nan => :null))
123
128
  assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge))
@@ -869,6 +869,14 @@ class ObjectJuice < Minitest::Test
869
869
  assert_equal(a2[1].__id__, a2.__id__)
870
870
  end
871
871
 
872
+ def test_circular_array3
873
+ a = ['^r1']
874
+ json = Oj.dump(a, mode: :object, circular: true)
875
+ assert_equal(%{["^i1","\\u005er1"]}, json)
876
+ a2 = Oj.load(json, mode: :object, circular: true)
877
+ assert_equal(a, a2)
878
+ end
879
+
872
880
  def test_circular_hash2
873
881
  h = { 'a' => 7 }
874
882
  h['b'] = h
@@ -185,7 +185,6 @@ class Juice < Minitest::Test
185
185
  n = Oj.load('-0.000012345678901234567')
186
186
  assert_equal(BigDecimal, n.class)
187
187
  assert_equal('-0.12345678901234567E-4', n.to_s.upcase)
188
-
189
188
  end
190
189
 
191
190
  =begin
@@ -671,7 +670,7 @@ class Juice < Minitest::Test
671
670
  raise e
672
671
  end
673
672
  }
674
- assert_equal('first[2].third', msg.split('(')[1].split(')')[0])
673
+ assert_equal('after first[2].third', msg.split('(')[1].split(')')[0])
675
674
  end
676
675
 
677
676
  def test_bad_bignum
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: 3.10.1
4
+ version: 3.10.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-14 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -219,6 +219,7 @@ files:
219
219
  - test/perf_simple.rb
220
220
  - test/perf_strict.rb
221
221
  - test/perf_wab.rb
222
+ - test/prec.rb
222
223
  - test/sample.rb
223
224
  - test/sample/change.rb
224
225
  - test/sample/dir.rb
@@ -283,12 +284,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
283
284
  - !ruby/object:Gem::Version
284
285
  version: '0'
285
286
  requirements: []
286
- rubygems_version: 3.0.3
287
+ rubygems_version: 3.1.2
287
288
  signing_key:
288
289
  specification_version: 4
289
290
  summary: A fast JSON parser and serializer.
290
291
  test_files:
291
292
  - test/foo.rb
293
+ - test/prec.rb
292
294
  - test/test_integer_range.rb
293
295
  - test/test_strict.rb
294
296
  - test/perf_strict.rb