oj 3.15.1 → 3.16.0

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: 257582096951b3c4db4b4979c49afd542ae855ba454bd6d51dcb1a69f68c2405
4
- data.tar.gz: d835a958d019f7034e93d3f97ca1829fad74a4e26743f6a8b2b581c03ac9f14a
3
+ metadata.gz: affe42de16d26dfe301f38df7c0bc8ceee39ab25e5a6bd14bd7af6671cc3b422
4
+ data.tar.gz: ee1d7227f864b197aca62cb767f9202798b6d3d13cf0b5f89eae3f3a36450dbb
5
5
  SHA512:
6
- metadata.gz: 374e55547de2db4b2199c05bebe5fa74953021883f7f609e328466c076016817b0cb8a7be03ead9c68b3fe4895eb5de0bcd60e1384ff7f1a5f7cd480824faba0
7
- data.tar.gz: ec9cf41116602a51c49ff73ba6fc39ecbb501d51cbab0a6065bb38d2ac15a7f42332dc66f0d97df40bea6da5fafbc15209d06039180829c4c4b299b0e138676e
6
+ metadata.gz: 8dbf6a0b5fef2b179dba864b595113f73ac27a952307559422bf1feda19fcc008a5e43a142d1bb3eb0cc4125ff18f35730208c7f82b11089ff90690e7b1f17d0
7
+ data.tar.gz: be09c04fa551288e2708c9151d0c966a09c3768ba15442cc54b8b4dd5850e2228b45608c06c8251c4e2ca32333353713f9c1feff81e4d34a48d1c6bf725014f6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.16.0 - 2023-08-16
4
+
5
+ - Added the `float_format` option.
6
+
7
+ - Expanded the `max_nesting` option to allow integer values as well as
8
+ the previous boolean (true or nil).
9
+
10
+ - Skip nesting tests with Truffle Ruby in the json gem tests.
11
+
3
12
  ## 3.15.1 - 2023-07-30
4
13
 
5
14
  - Add protection against some using `require 'oj/json`, an internal file.
data/ext/oj/dump_compat.c CHANGED
@@ -851,13 +851,18 @@ static DumpFunc compat_funcs[] = {
851
851
  };
852
852
 
853
853
  static void set_state_depth(VALUE state, int depth) {
854
- VALUE json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
855
- VALUE ext = rb_const_get(json_module, rb_intern("Ext"));
856
- VALUE generator = rb_const_get(ext, rb_intern("Generator"));
857
- VALUE state_class = rb_const_get(generator, rb_intern("State"));
854
+ if (0 == rb_const_defined(rb_cObject, rb_intern("JSON"))) {
855
+ rb_require("oj/json");
856
+ }
857
+ {
858
+ VALUE json_module = rb_const_get_at(rb_cObject, rb_intern("JSON"));
859
+ VALUE ext = rb_const_get(json_module, rb_intern("Ext"));
860
+ VALUE generator = rb_const_get(ext, rb_intern("Generator"));
861
+ VALUE state_class = rb_const_get(generator, rb_intern("State"));
858
862
 
859
- if (state_class == rb_obj_class(state)) {
860
- rb_funcall(state, rb_intern("depth="), 1, INT2NUM(depth));
863
+ if (state_class == rb_obj_class(state)) {
864
+ rb_funcall(state, rb_intern("depth="), 1, INT2NUM(depth));
865
+ }
861
866
  }
862
867
  }
863
868
 
@@ -865,20 +870,15 @@ void oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
865
870
  int type = rb_type(obj);
866
871
 
867
872
  TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
873
+ // The max_nesting logic is that an empty Array or Hash is assumed to have
874
+ // content so the max_nesting should fail but a non-collection value is
875
+ // okay. That means a check for a collectable value is needed before
876
+ // raising.
868
877
  if (out->opts->dump_opts.max_depth <= depth) {
869
- // When JSON.dump is called then an ArgumentError is expected and the
870
- // limit is the depth inclusive. If JSON.generate is called then a
871
- // NestingError is expected and the limit is inclusive. Worse than
872
- // that there are unit tests for both.
873
- if (CALLER_DUMP == out->caller) {
878
+ if (RUBY_T_ARRAY == type || RUBY_T_HASH == type) {
874
879
  if (0 < out->argc) {
875
880
  set_state_depth(*out->argv, depth);
876
881
  }
877
- rb_raise(rb_eArgError, "Too deeply nested.");
878
- } else if (out->opts->dump_opts.max_depth < depth) {
879
- if (0 < out->argc) {
880
- set_state_depth(*out->argv, depth - 1);
881
- }
882
882
  raise_json_err("Too deeply nested", "NestingError");
883
883
  }
884
884
  }
data/ext/oj/mimic_json.c CHANGED
@@ -209,7 +209,6 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
209
209
 
210
210
  oj_out_init(&out);
211
211
 
212
- out.caller = CALLER_DUMP;
213
212
  copts.escape_mode = JXEsc;
214
213
  copts.mode = CompatMode;
215
214
 
@@ -368,7 +367,6 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
368
367
  oj_out_init(&out);
369
368
 
370
369
  out.omit_nil = copts->dump_opts.omit_nil;
371
- out.caller = CALLER_GENERATE;
372
370
  // For obj.to_json or generate nan is not allowed but if called from dump
373
371
  // it is.
374
372
  copts->dump_opts.nan_dump = RaiseNan;
data/ext/oj/oj.c CHANGED
@@ -123,6 +123,7 @@ static VALUE escape_mode_sym;
123
123
  static VALUE integer_range_sym;
124
124
  static VALUE fast_sym;
125
125
  static VALUE float_prec_sym;
126
+ static VALUE float_format_sym;
126
127
  static VALUE float_sym;
127
128
  static VALUE huge_sym;
128
129
  static VALUE ignore_sym;
@@ -232,7 +233,7 @@ struct _options oj_default_options = {
232
233
  NULL, // tail
233
234
  {'\0'}, // err
234
235
  },
235
- NULL, // ignore
236
+ NULL,
236
237
  };
237
238
 
238
239
  /* Document-method: default_options()
@@ -267,6 +268,8 @@ struct _options oj_default_options = {
267
268
  *seconds portion of time
268
269
  * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0
269
270
  *indicates use Ruby
271
+ * - *:float_format* [_String_] the C printf format string for printing floats. Default follows
272
+ * the float_precision and will be changed if float_precision is changed. The string can be no more than 6 bytes.
270
273
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
271
274
  * - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
272
275
  * - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false
@@ -378,6 +381,7 @@ static VALUE get_def_opts(VALUE self) {
378
381
  oj_safe_sym,
379
382
  (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
380
383
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
384
+ rb_hash_aset(opts, float_format_sym, rb_str_new_cstr(oj_default_options.float_fmt));
381
385
  rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
382
386
  rb_hash_aset(
383
387
  opts,
@@ -519,6 +523,8 @@ static VALUE get_def_opts(VALUE self) {
519
523
  *load.
520
524
  * - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the
521
525
  *seconds portion of time.
526
+ * - *:float_format* [_String_] the C printf format string for printing floats. Default follows
527
+ * the float_precision and will be changed if float_precision is changed. The string can be no more than 6 bytes.
522
528
  * - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0
523
529
  *indicates use Ruby.
524
530
  * - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
@@ -617,7 +623,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
617
623
  if (set_yesno_options(k, v, copts)) {
618
624
  return ST_CONTINUE;
619
625
  }
620
-
621
626
  if (oj_indent_sym == k) {
622
627
  switch (rb_type(v)) {
623
628
  case T_NIL:
@@ -757,7 +762,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
757
762
  if (Qnil == v) {
758
763
  return ST_CONTINUE;
759
764
  }
760
-
761
765
  copts->compat_bigdec = (Qtrue == v);
762
766
  } else if (oj_decimal_class_sym == k) {
763
767
  if (rb_cFloat == v) {
@@ -949,6 +953,25 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
949
953
  return ST_CONTINUE;
950
954
  }
951
955
  copts->sym_key = (Qtrue == v) ? Yes : No;
956
+
957
+ } else if (oj_max_nesting_sym == k) {
958
+ if (Qtrue == v) {
959
+ copts->dump_opts.max_depth = 100;
960
+ } else if (Qfalse == v || Qnil == v) {
961
+ copts->dump_opts.max_depth = MAX_DEPTH;
962
+ } else if (T_FIXNUM == rb_type(v)) {
963
+ copts->dump_opts.max_depth = NUM2INT(v);
964
+ if (0 >= copts->dump_opts.max_depth) {
965
+ copts->dump_opts.max_depth = MAX_DEPTH;
966
+ }
967
+ }
968
+ } else if (float_format_sym == k) {
969
+ rb_check_type(v, T_STRING);
970
+ if (6 < (int)RSTRING_LEN(v)) {
971
+ rb_raise(rb_eArgError, ":float_format must be 6 bytes or less.");
972
+ }
973
+ strncpy(copts->float_fmt, RSTRING_PTR(v), (size_t)RSTRING_LEN(v));
974
+ copts->float_fmt[RSTRING_LEN(v)] = '\0';
952
975
  }
953
976
  return ST_CONTINUE;
954
977
  }
@@ -957,7 +980,6 @@ void oj_parse_options(VALUE ropts, Options copts) {
957
980
  if (T_HASH != rb_type(ropts)) {
958
981
  return;
959
982
  }
960
-
961
983
  rb_hash_foreach(ropts, parse_options_cb, (VALUE)copts);
962
984
  oj_parse_opt_match_string(&copts->str_rx, ropts);
963
985
 
@@ -1296,7 +1318,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1296
1318
 
1297
1319
  arg.out->omit_nil = copts.dump_opts.omit_nil;
1298
1320
  arg.out->omit_null_byte = copts.dump_opts.omit_null_byte;
1299
- arg.out->caller = CALLER_DUMP;
1300
1321
 
1301
1322
  return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
1302
1323
  }
@@ -1308,8 +1329,9 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1308
1329
  * will be called. The mode is set to :compat.
1309
1330
  * - *obj* [_Object_] Object to serialize as an JSON document String
1310
1331
  * - *options* [_Hash_]
1311
- * - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular
1312
- * references is available but is not compatible with the json gem., default is false
1332
+ * - *:max_nesting* [_Fixnum_|_boolean_] It true nesting is limited to 100. If a Fixnum nesting
1333
+ * is set to the provided value. The option to detect circular references is available but is not
1334
+ * compatible with the json gem., default is false or unlimited.
1313
1335
  * - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be
1314
1336
  * used as appropriate, default is true.
1315
1337
  * - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true
@@ -1929,6 +1951,8 @@ void Init_oj(void) {
1929
1951
  rb_gc_register_address(&integer_range_sym);
1930
1952
  fast_sym = ID2SYM(rb_intern("fast"));
1931
1953
  rb_gc_register_address(&fast_sym);
1954
+ float_format_sym = ID2SYM(rb_intern("float_format"));
1955
+ rb_gc_register_address(&float_format_sym);
1932
1956
  float_prec_sym = ID2SYM(rb_intern("float_precision"));
1933
1957
  rb_gc_register_address(&float_prec_sym);
1934
1958
  float_sym = ID2SYM(rb_intern("float"));
data/ext/oj/oj.h CHANGED
@@ -103,13 +103,6 @@ typedef enum {
103
103
  FILE_IO = 'f',
104
104
  } StreamWriterType;
105
105
 
106
- typedef enum {
107
- CALLER_DUMP = 'd',
108
- CALLER_TO_JSON = 't',
109
- CALLER_GENERATE = 'g',
110
- // Add the fast versions if necessary. Maybe unparse as well if needed.
111
- } DumpCaller;
112
-
113
106
  typedef struct _dumpOpts {
114
107
  bool use;
115
108
  char indent_str[16];
@@ -188,23 +181,22 @@ typedef struct _rOptTable {
188
181
  } *ROptTable;
189
182
 
190
183
  typedef struct _out {
191
- char stack_buffer[4096];
192
- char *buf;
193
- char *end;
194
- char *cur;
195
- Cache8 circ_cache;
196
- slot_t circ_cnt;
197
- int indent;
198
- int depth; // used by dump_hash
199
- Options opts;
200
- uint32_t hash_cnt;
201
- bool allocated;
202
- bool omit_nil;
203
- bool omit_null_byte;
204
- int argc;
205
- VALUE *argv;
206
- DumpCaller caller; // used for the mimic json only
207
- ROptTable ropts;
184
+ char stack_buffer[4096];
185
+ char *buf;
186
+ char *end;
187
+ char *cur;
188
+ Cache8 circ_cache;
189
+ slot_t circ_cnt;
190
+ int indent;
191
+ int depth; // used by dump_hash
192
+ Options opts;
193
+ uint32_t hash_cnt;
194
+ bool allocated;
195
+ bool omit_nil;
196
+ bool omit_null_byte;
197
+ int argc;
198
+ VALUE *argv;
199
+ ROptTable ropts;
208
200
  } *Out;
209
201
 
210
202
  typedef struct _strWriter {
data/ext/oj/rails.c CHANGED
@@ -890,7 +890,6 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
890
890
  oj_out_init(&out);
891
891
 
892
892
  out.omit_nil = copts.dump_opts.omit_nil;
893
- out.caller = 0;
894
893
  out.cur = out.buf;
895
894
  out.circ_cnt = 0;
896
895
  out.opts = &copts;
@@ -70,7 +70,6 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
70
70
  sw->out.depth = 0;
71
71
  sw->out.argc = 0;
72
72
  sw->out.argv = NULL;
73
- sw->out.caller = 0;
74
73
  sw->out.ropts = NULL;
75
74
  sw->out.omit_nil = oj_default_options.dump_opts.omit_nil;
76
75
  }
data/lib/oj/json.rb CHANGED
@@ -2,7 +2,10 @@ require 'ostruct'
2
2
  require 'oj/state'
3
3
 
4
4
  if defined?(JSON::PRETTY_STATE_PROTOTYPE)
5
- warn "WARNING: oj/json is a compatability shim used by Oj. Requiring the file explicitly is no recommended."
5
+ # There are enough people that try to use both the json gen and oj in mimic
6
+ # mode so don't display the warning.
7
+
8
+ # warn "WARNING: oj/json is a compatability shim used by Oj. Requiring the file explicitly is not recommended."
6
9
  end
7
10
 
8
11
  unless defined?(JSON::PRETTY_STATE_PROTOTYPE)
data/lib/oj/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Oj
2
2
  # Current version of the module.
3
- VERSION = '3.15.1'
3
+ VERSION = '3.16.0'
4
4
  end
data/test/foo.rb CHANGED
@@ -5,16 +5,10 @@ $LOAD_PATH << '.'
5
5
  $LOAD_PATH << File.join(__dir__, '../lib')
6
6
  $LOAD_PATH << File.join(__dir__, '../ext')
7
7
 
8
- require 'active_support'
9
8
  require 'json'
10
9
  require 'oj'
10
+ require 'oj/json'
11
11
 
12
- Oj.mimic_JSON()
13
- # Oj::Rails.mimic_JSON()
12
+ Oj.mimic_JSON
14
13
 
15
- begin
16
- ::JSON.parse('{ "foo": 84e }')
17
- #::JSON.parse('{ "foo": 84eb234 }')
18
- rescue Exception => e
19
- puts "#{e.class}: #{e.message}"
20
- end
14
+ JSON.parse("[]")
@@ -128,8 +128,10 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
128
128
  too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
129
129
  assert_equal too_deep, JSON.dump(eval(too_deep))
130
130
  assert_kind_of String, Marshal.dump(eval(too_deep))
131
- assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
132
- assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
131
+ if RUBY_ENGINE != 'truffleruby'
132
+ assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
133
+ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
134
+ end
133
135
  assert_equal too_deep, JSON.dump(eval(too_deep), 101)
134
136
  assert_kind_of String, Marshal.dump(eval(too_deep), 101)
135
137
  output = StringIO.new
@@ -352,7 +352,7 @@ class JSONGeneratorTest < Test::Unit::TestCase
352
352
  too_deep_ary = eval too_deep
353
353
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
354
354
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
355
- ok = JSON.generate too_deep_ary, :max_nesting => 101
355
+ ok = JSON.generate too_deep_ary, :max_nesting => 102
356
356
  assert_equal too_deep, ok
357
357
  ok = JSON.generate too_deep_ary, :max_nesting => nil
358
358
  assert_equal too_deep, ok
data/test/perf_dump.rb CHANGED
@@ -28,7 +28,7 @@ opts.parse(ARGV)
28
28
  'd' => [ true, [false, [-123_456_789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
29
29
  'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
30
30
  'f' => nil, # nil
31
- 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
31
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => { 'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
32
32
  'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
33
33
  }
34
34
 
data/test/prec.rb CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'oj'
4
4
 
5
- extras = {'locationLng' => -97.14690769100295}
5
+ extras = { 'locationLng' => -97.14690769100295 }
6
6
 
7
- Oj.default_options = {float_precision: 17}
7
+ Oj.default_options = { float_precision: 17 }
8
8
 
9
9
  encoded = Oj.dump(extras)
10
10
  puts encoded
@@ -15,8 +15,8 @@ require 'active_record'
15
15
  Oj::Rails.set_encoder()
16
16
  Oj::Rails.set_decoder()
17
17
 
18
- Oj.default_options = {float_precision: 17}
19
- # Using Oj rails encoder, gets the correct value: {'locationLng':-97.14690769100295}
18
+ Oj.default_options = { float_precision: 17 }
19
+ # Using Oj rails encoder, gets the correct value: { 'locationLng':-97.14690769100295 }
20
20
  encoded = ActiveSupport::JSON.encode(extras)
21
21
  puts encoded
22
22
  puts ActiveSupport::JSON.decode(encoded)
data/test/test_compat.rb CHANGED
@@ -467,10 +467,28 @@ class CompatJuice < Minitest::Test
467
467
  end
468
468
 
469
469
  def test_arg_passing
470
- json = Oj.to_json(Argy.new(), :max_nesting=> 40)
470
+ json = Oj.to_json(Argy.new(), :max_nesting => 40)
471
471
  assert_equal(%|{"args":"[{:max_nesting=>40}]"}|, json)
472
472
  end
473
473
 
474
+ def test_max_nesting
475
+ assert_raises() { Oj.to_json([[[[[]]]]], :max_nesting => 3) }
476
+ assert_raises() { Oj.dump([[[[[]]]]], :max_nesting => 3, :mode=>:compat) }
477
+
478
+ assert_raises() { Oj.to_json([[]], :max_nesting => 1) }
479
+ assert_equal('[[]]', Oj.to_json([[]], :max_nesting => 2))
480
+
481
+ assert_raises() { Oj.dump([[]], :max_nesting => 1, :mode=>:compat) }
482
+ assert_equal('[[]]', Oj.dump([[]], :max_nesting => 2, :mode=>:compat))
483
+
484
+ assert_raises() { Oj.to_json([[3]], :max_nesting => 1) }
485
+ assert_equal('[[3]]', Oj.to_json([[3]], :max_nesting => 2))
486
+
487
+ assert_raises() { Oj.dump([[3]], :max_nesting => 1, :mode=>:compat) }
488
+ assert_equal('[[3]]', Oj.dump([[3]], :max_nesting => 2, :mode=>:compat))
489
+
490
+ end
491
+
474
492
  def test_bad_unicode
475
493
  assert_raises() { Oj.to_json("\xE4xy") }
476
494
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  $LOAD_PATH << __dir__
5
5
  @oj_dir = File.dirname(File.expand_path(__dir__))
6
- %w(lib ext).each do |dir|
6
+ %w[lib ext].each do |dir|
7
7
  $LOAD_PATH << File.join(@oj_dir, dir)
8
8
  end
9
9
 
data/test/test_various.rb CHANGED
@@ -105,6 +105,7 @@ class Juice < Minitest::Test
105
105
  allow_gc: false,
106
106
  quirks_mode: false,
107
107
  allow_invalid_unicode: true,
108
+ float_format: '%0.13g',
108
109
  float_precision: 13,
109
110
  mode: :strict,
110
111
  escape_mode: :ascii,
@@ -416,6 +417,11 @@ class Juice < Minitest::Test
416
417
  }
417
418
  end
418
419
 
420
+ def test_dump_float
421
+ json = Oj.dump(1.23e-2, :mode => :null, :float_format => '%0.4f')
422
+ assert_equal('0.0123', json)
423
+ end
424
+
419
425
  # Class
420
426
  def test_class_null
421
427
  json = Oj.dump(Juice, :mode => :null)
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.15.1
4
+ version: 3.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-31 00:00:00.000000000 Z
11
+ date: 2023-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest