oj 3.10.1 → 3.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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