oj 3.9.2 → 3.10.0

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: 52a998aa9f2273e995d9ef52e26df3f8998aae1a98d7d088f6973cf8234a444f
4
- data.tar.gz: 26647fb39df6d357074e5798bf263ca708a361cf910eba43c7c7a3d1ba905f51
3
+ metadata.gz: 62a52be7754c5ef34c3006fb28fa918cb18f23c26ffa94e8daedf05396bbe0fb
4
+ data.tar.gz: 9cf9cfab00cf1e28f8b42c6d3e88ee6a2a785093cc024c558eeceb25eaf39cd1
5
5
  SHA512:
6
- metadata.gz: 9dffec2bd8c447ca172aa4a647a719c1cc62eeedab91ea30b79943fa212e4b78a10b3e3ddfd69e873e632c3bdddce2d955d34aa106dfa7e4f43618ea842aa829
7
- data.tar.gz: 5dd30d0dcaf87e9b57c16ad13f0e7654ab8b8b02d8b3709f20614025283101bc44cedf4470bb2bb887b41a280d2e4b131f77a26a65a8e79447771a6bc5cca42d
6
+ metadata.gz: 931cf30643fc1be050ec4f3c0c69f85b643b073e7bd5d16c5c8a5431c8d3701ae73fc5b68311246f2db993fa1c3e40b6169978f10b377a947cc937a7d26afd6e
7
+ data.tar.gz: 779d173d00513d830f825cc9e0f51a5a066beece8fe9289d1face779c34210d6f7506e8e8af380fc5f2d3c2dd727b46f14cc985d4a2867e3a71fb1de4217361a
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
2
2
 
3
- [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
3
+ [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg?logo=travis)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg?logo=appveyor)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [![TideLift](https://tidelift.com/badges/github/ohler55/oj)](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
4
4
 
5
5
  A *fast* JSON parser and Object marshaller as a Ruby gem.
6
6
 
@@ -42,7 +42,7 @@ gem 'oj'
42
42
 
43
43
  ## Support
44
44
 
45
- [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
45
+ [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
46
46
 
47
47
  ## Further Reading
48
48
 
@@ -609,6 +609,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
609
609
  // the key name is NULL. Not an empty string but NULL.
610
610
  if (NULL == attr) {
611
611
  attr = "";
612
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
613
+ return ST_CONTINUE;
612
614
  }
613
615
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
614
616
  return ST_CONTINUE;
@@ -548,7 +548,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
548
548
  tzhour = (int)(tzsecs / 3600);
549
549
  tzmin = (int)(tzsecs / 60) - (tzhour * 60);
550
550
  }
551
- if (0 == nsec || 0 == out->opts->sec_prec) {
551
+ if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
552
552
  if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
553
553
  sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
554
554
  oj_dump_cstr(buf, 20, 0, 0, out);
@@ -1023,8 +1023,8 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1023
1023
  int neg = 0;
1024
1024
  bool dump_as_string = false;
1025
1025
 
1026
- if (out->opts->integer_range_max != 0 && out->opts->integer_range_min != 0 &&
1027
- (out->opts->integer_range_max < num || out->opts->integer_range_min > num)) {
1026
+ if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
1027
+ (out->opts->int_range_max < num || out->opts->int_range_min > num)) {
1028
1028
  dump_as_string = true;
1029
1029
  }
1030
1030
  if (0 > num) {
@@ -1062,23 +1062,20 @@ void
1062
1062
  oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
1063
1063
  volatile VALUE rs = rb_big2str(obj, 10);
1064
1064
  int cnt = (int)RSTRING_LEN(rs);
1065
- bool dump_as_string = false;
1065
+ bool dump_as_string = false;
1066
1066
 
1067
- if (out->opts->integer_range_max != 0 || out->opts->integer_range_min != 0) { // Bignum cannot be inside of Fixnum range
1067
+ if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
1068
1068
  dump_as_string = true;
1069
1069
  assure_size(out, cnt + 2);
1070
1070
  *out->cur++ = '"';
1071
- } else {
1071
+ } else {
1072
1072
  assure_size(out, cnt);
1073
- }
1074
-
1073
+ }
1075
1074
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
1076
1075
  out->cur += cnt;
1077
-
1078
- if(dump_as_string) {
1076
+ if (dump_as_string) {
1079
1077
  *out->cur++ = '"';
1080
- }
1081
-
1078
+ }
1082
1079
  *out->cur = '\0';
1083
1080
  }
1084
1081
 
@@ -870,7 +870,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
870
870
  // this must use to_s to pass the json gem unit tests.
871
871
  volatile VALUE rs;
872
872
  int cnt;
873
- bool dump_as_string = false;
873
+ bool dump_as_string = false;
874
874
 
875
875
  if (use_bignum_alt) {
876
876
  rs = rb_big2str(obj, 10);
@@ -880,21 +880,18 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
880
880
  rb_check_type(rs, T_STRING);
881
881
  cnt = (int)RSTRING_LEN(rs);
882
882
 
883
- if (out->opts->integer_range_min != 0 || out->opts->integer_range_max != 0) {
883
+ if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
884
884
  dump_as_string = true; // Bignum cannot be inside of Fixnum range
885
885
  assure_size(out, cnt + 2);
886
886
  *out->cur++ = '"';
887
- } else {
887
+ } else {
888
888
  assure_size(out, cnt);
889
- }
890
-
889
+ }
891
890
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
892
891
  out->cur += cnt;
893
-
894
- if(dump_as_string) {
892
+ if (dump_as_string) {
895
893
  *out->cur++ = '"';
896
- }
897
-
894
+ }
898
895
  *out->cur = '\0';
899
896
  }
900
897
 
@@ -56,7 +56,7 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
56
56
  }
57
57
  } else {
58
58
  long id = oj_check_circular(obj, out);
59
-
59
+
60
60
  if (0 <= id) {
61
61
  dump_obj_attrs(obj, clas, id, depth, out);
62
62
  }
@@ -72,7 +72,7 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
72
72
  volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
73
73
  const char *str = rb_string_value_ptr((VALUE*)&rstr);
74
74
  int len = (int)RSTRING_LEN(rstr);
75
-
75
+
76
76
  if (0 == strcasecmp("Infinity", str)) {
77
77
  str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
78
78
  oj_dump_raw(str, len, out);
@@ -280,7 +280,7 @@ hash_cb(VALUE key, VALUE value, Out out) {
280
280
  }
281
281
  out->depth = depth;
282
282
  *out->cur++ = ',';
283
-
283
+
284
284
  return ST_CONTINUE;
285
285
  }
286
286
 
@@ -363,6 +363,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
363
363
  // the key name is NULL. Not an empty string but NULL.
364
364
  if (NULL == attr) {
365
365
  attr = "";
366
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
367
+ return ST_CONTINUE;
366
368
  }
367
369
  if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
368
370
  return ST_CONTINUE;
@@ -384,7 +386,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
384
386
  oj_dump_obj_val(value, depth, out);
385
387
  out->depth = depth;
386
388
  *out->cur++ = ',';
387
-
389
+
388
390
  return ST_CONTINUE;
389
391
  }
390
392
  #endif
@@ -424,7 +426,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
424
426
  v = rb_funcall(obj, *odd->attrs, 0);
425
427
  if (Qundef == v || T_STRING != rb_type(v)) {
426
428
  rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
427
- } else {
429
+ } else {
428
430
  const char *s = rb_string_value_ptr((VALUE*)&v);
429
431
  int len = (int)RSTRING_LEN(v);
430
432
  const char *name = rb_id2name(*odd->attrs);
@@ -460,7 +462,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
460
462
  char *n;
461
463
  char *end;
462
464
  ID i;
463
-
465
+
464
466
  if (sizeof(nbuf) <= nlen) {
465
467
  if (NULL == (n2 = strdup(name))) {
466
468
  rb_raise(rb_eNoMemError, "for attribute name.");
@@ -610,9 +612,12 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
610
612
  size = d2 * out->indent + 1;
611
613
  for (i = cnt; 0 < i; i--, np++) {
612
614
  VALUE value;
613
-
615
+
614
616
  vid = rb_to_id(*np);
615
617
  attr = rb_id2name(vid);
618
+ if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
619
+ return ST_CONTINUE;
620
+ }
616
621
  value = rb_ivar_get(obj, vid);
617
622
 
618
623
  if (oj_dump_ignore(out->opts, value)) {
@@ -739,7 +744,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
739
744
  #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
740
745
  cnt = (int)RSTRUCT_LEN(obj);
741
746
  #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
742
-
747
+
743
748
  for (i = 0; i < cnt; i++) {
744
749
  v = RSTRUCT_GET(obj, i);
745
750
  if (oj_dump_ignore(out->opts, v)) {
@@ -812,7 +817,7 @@ static DumpFunc obj_funcs[] = {
812
817
  void
813
818
  oj_dump_obj_val(VALUE obj, int depth, Out out) {
814
819
  int type = rb_type(obj);
815
-
820
+
816
821
  if (Yes == out->opts->trace) {
817
822
  oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
818
823
  }
@@ -690,8 +690,10 @@ static struct _options mimic_object_to_json_options = {
690
690
  No, // allow_nan
691
691
  No, // trace
692
692
  No, // safe
693
- 0, // integer_range_min
694
- 0, // integer_range_max
693
+ false, // sec_prec_set
694
+ No, // ignore_under
695
+ 0, // int_range_min
696
+ 0, // int_range_max
695
697
  oj_json_class,// create_id
696
698
  10, // create_id_len
697
699
  3, // sec_prec
@@ -119,6 +119,7 @@ static VALUE float_prec_sym;
119
119
  static VALUE float_sym;
120
120
  static VALUE huge_sym;
121
121
  static VALUE ignore_sym;
122
+ static VALUE ignore_under_sym;
122
123
  static VALUE json_sym;
123
124
  static VALUE match_string_sym;
124
125
  static VALUE mode_sym;
@@ -181,8 +182,10 @@ struct _options oj_default_options = {
181
182
  Yes, // allow_nan
182
183
  No, // trace
183
184
  No, // safe
184
- 0, // integer_range_min
185
- 0, // integer_range_max
185
+ false, // sec_prec_set
186
+ No, // ignore_under
187
+ 0, // int_range_min
188
+ 0, // int_range_max
186
189
  oj_json_class, // create_id
187
190
  10, // create_id_len
188
191
  9, // sec_prec
@@ -251,6 +254,7 @@ struct _options oj_default_options = {
251
254
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
252
255
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
253
256
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
257
+ * - *:ignore_under* [Boolean] if true then attributes that start with _ are ignored when dumping in object or custom mode.
254
258
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
255
259
  * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
256
260
  * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is off)
@@ -286,6 +290,7 @@ get_def_opts(VALUE self) {
286
290
  rb_hash_aset(opts, oj_trace_sym, (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
287
291
  rb_hash_aset(opts, oj_safe_sym, (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
288
292
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
293
+ rb_hash_aset(opts, ignore_under_sym, (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
289
294
  switch (oj_default_options.mode) {
290
295
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
291
296
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -297,16 +302,16 @@ get_def_opts(VALUE self) {
297
302
  default: rb_hash_aset(opts, mode_sym, object_sym); break;
298
303
  }
299
304
 
300
- if (oj_default_options.integer_range_max != 0 || oj_default_options.integer_range_min != 0) {
301
- VALUE range = rb_obj_alloc(rb_cRange);
302
- VALUE min = LONG2FIX(oj_default_options.integer_range_min);
303
- VALUE max = LONG2FIX(oj_default_options.integer_range_max);
304
- rb_ivar_set(range, oj_begin_id, min);
305
- rb_ivar_set(range, oj_end_id, max);
306
- rb_hash_aset(opts, integer_range_sym, range);
307
- }
308
- else {
309
- rb_hash_aset(opts, integer_range_sym, Qnil);
305
+ if (oj_default_options.int_range_max != 0 || oj_default_options.int_range_min != 0) {
306
+ VALUE range = rb_obj_alloc(rb_cRange);
307
+ VALUE min = LONG2FIX(oj_default_options.int_range_min);
308
+ VALUE max = LONG2FIX(oj_default_options.int_range_max);
309
+
310
+ rb_ivar_set(range, oj_begin_id, min);
311
+ rb_ivar_set(range, oj_end_id, max);
312
+ rb_hash_aset(opts, integer_range_sym, range);
313
+ } else {
314
+ rb_hash_aset(opts, integer_range_sym, Qnil);
310
315
  }
311
316
  switch (oj_default_options.escape_mode) {
312
317
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
@@ -398,6 +403,7 @@ get_def_opts(VALUE self) {
398
403
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
399
404
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
400
405
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
406
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in object or custom mode.
401
407
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
402
408
  * - *:trace* [_Boolean_] turn trace on or off.
403
409
  * - *:safe* [_Boolean_] turn safe mimic on or off.
@@ -431,6 +437,7 @@ oj_parse_options(VALUE ropts, Options copts) {
431
437
  { oj_allow_nan_sym, &copts->allow_nan },
432
438
  { oj_trace_sym, &copts->trace },
433
439
  { oj_safe_sym, &copts->safe },
440
+ { ignore_under_sym, &copts->ignore_under },
434
441
  { oj_create_additions_sym, &copts->create_ok },
435
442
  { Qnil, 0 }
436
443
  };
@@ -506,8 +513,12 @@ oj_parse_options(VALUE ropts, Options copts) {
506
513
  n = NUM2INT(v);
507
514
  if (0 > n) {
508
515
  n = 0;
516
+ copts->sec_prec_set = false;
509
517
  } else if (9 < n) {
510
518
  n = 9;
519
+ copts->sec_prec_set = true;
520
+ } else {
521
+ copts->sec_prec_set = true;
511
522
  }
512
523
  copts->sec_prec = n;
513
524
  }
@@ -738,19 +749,19 @@ oj_parse_options(VALUE ropts, Options copts) {
738
749
  }
739
750
  }
740
751
  if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
741
- if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
742
- VALUE min = rb_funcall(v, oj_begin_id, 0);
743
- VALUE max = rb_funcall(v, oj_end_id, 0);
744
-
745
- if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
746
- rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
747
- }
748
-
749
- copts->integer_range_min = FIX2LONG(min);
750
- copts->integer_range_max = FIX2LONG(max);
751
- } else if (Qfalse != v) {
752
- rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
753
- }
752
+ if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
753
+ VALUE min = rb_funcall(v, oj_begin_id, 0);
754
+ VALUE max = rb_funcall(v, oj_end_id, 0);
755
+
756
+ if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
757
+ rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
758
+ }
759
+
760
+ copts->int_range_min = FIX2LONG(min);
761
+ copts->int_range_max = FIX2LONG(max);
762
+ } else if (Qfalse != v) {
763
+ rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
764
+ }
754
765
  }
755
766
  }
756
767
 
@@ -954,11 +965,13 @@ load_file(int argc, VALUE *argv, VALUE self) {
954
965
  }
955
966
  switch (mode) {
956
967
  case StrictMode:
968
+ case NullMode:
957
969
  oj_set_strict_callbacks(&pi);
958
970
  return oj_pi_sparse(argc, argv, &pi, fd);
959
- case NullMode:
960
- case CompatMode:
961
971
  case CustomMode:
972
+ oj_set_custom_callbacks(&pi);
973
+ return oj_pi_sparse(argc, argv, &pi, fd);
974
+ case CompatMode:
962
975
  case RailsMode:
963
976
  oj_set_compat_callbacks(&pi);
964
977
  return oj_pi_sparse(argc, argv, &pi, fd);
@@ -1052,6 +1065,9 @@ dump(int argc, VALUE *argv, VALUE self) {
1052
1065
  if (2 == argc) {
1053
1066
  oj_parse_options(argv[1], &copts);
1054
1067
  }
1068
+ if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
1069
+ copts.escape_mode = JSONEsc;
1070
+ }
1055
1071
  out.buf = buf;
1056
1072
  out.end = buf + sizeof(buf) - 10;
1057
1073
  out.allocated = false;
@@ -1640,6 +1656,7 @@ Init_oj() {
1640
1656
  float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
1641
1657
  huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
1642
1658
  ignore_sym = ID2SYM(rb_intern("ignore")); rb_gc_register_address(&ignore_sym);
1659
+ ignore_under_sym = ID2SYM(rb_intern("ignore_under")); rb_gc_register_address(&ignore_under_sym);
1643
1660
  json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
1644
1661
  match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
1645
1662
  mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
@@ -149,8 +149,10 @@ typedef struct _options {
149
149
  char allow_nan; // YEsyNo for parsing only
150
150
  char trace; // YesNo
151
151
  char safe; // YesNo
152
- int64_t integer_range_min; // dump numbers outside range as string
153
- int64_t integer_range_max;
152
+ char sec_prec_set; // boolean (0 or 1)
153
+ char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
154
+ int64_t int_range_min; // dump numbers below as string
155
+ int64_t int_range_max; // dump numbers above as string
154
156
  const char *create_id; // 0 or string
155
157
  size_t create_id_len; // length of create_id
156
158
  int sec_prec; // second precision when dumping time
@@ -400,6 +400,10 @@ read_num(ParseInfo pi) {
400
400
  pi->cur++;
401
401
  ni.neg = 1;
402
402
  } else if ('+' == *pi->cur) {
403
+ if (StrictMode == pi->options.mode) {
404
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
405
+ return;
406
+ }
403
407
  pi->cur++;
404
408
  }
405
409
  if ('I' == *pi->cur) {
@@ -446,8 +450,13 @@ read_num(ParseInfo pi) {
446
450
  if ('.' == *pi->cur) {
447
451
  pi->cur++;
448
452
  // A trailing . is not a valid decimal but if encountered allow it
449
- // except when mimicing the JSON gem.
450
- if (CompatMode == pi->options.mode) {
453
+ // except when mimicing the JSON gem or in strict mode.
454
+ if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
455
+ int pos = (int)(pi->cur - ni.str);
456
+ if (1 == pos || (2 == pos && ni.neg)) {
457
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
458
+ return;
459
+ }
451
460
  if (*pi->cur < '0' || '9' < *pi->cur) {
452
461
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
453
462
  return;
@@ -1050,7 +1059,7 @@ CLEANUP:
1050
1059
  }
1051
1060
  args[0] = msg;
1052
1061
  if (pi->err.clas == oj_parse_error_class) {
1053
- // The error was an Oj::ParseError so change to a JSON::ParseError.
1062
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
1054
1063
  pi->err.clas = oj_json_parser_error_class;
1055
1064
  }
1056
1065
  rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
@@ -80,6 +80,7 @@ extern VALUE oj_num_as_value(NumInfo ni);
80
80
  extern void oj_set_strict_callbacks(ParseInfo pi);
81
81
  extern void oj_set_object_callbacks(ParseInfo pi);
82
82
  extern void oj_set_compat_callbacks(ParseInfo pi);
83
+ extern void oj_set_custom_callbacks(ParseInfo pi);
83
84
  extern void oj_set_wab_callbacks(ParseInfo pi);
84
85
 
85
86
  extern void oj_sparse2(ParseInfo pi);
@@ -214,6 +214,8 @@ dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
214
214
 
215
215
  if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
216
216
  oj_dump_nil(Qnil, depth, out, false);
217
+ } else if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) {
218
+ oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
217
219
  } else if (Yes == out->opts->bigdec_as_num) {
218
220
  oj_dump_raw(str, (int)RSTRING_LEN(rstr), out);
219
221
  } else {
@@ -1035,6 +1037,7 @@ static VALUE
1035
1037
  rails_time_precision(VALUE self, VALUE prec) {
1036
1038
  rb_iv_set(self, "@time_precision", prec);
1037
1039
  oj_default_options.sec_prec = NUM2INT(prec);
1040
+ oj_default_options.sec_prec_set = true;
1038
1041
 
1039
1042
  return prec;
1040
1043
  }
@@ -1078,6 +1081,7 @@ rails_set_encoder(VALUE self) {
1078
1081
 
1079
1082
  pv = rb_iv_get(encoding, "@time_precision");
1080
1083
  oj_default_options.sec_prec = NUM2INT(pv);
1084
+ oj_default_options.sec_prec_set = true;
1081
1085
  rb_undef_method(encoding, "time_precision=");
1082
1086
  rb_define_module_function(encoding, "time_precision=", rails_time_precision, 1);
1083
1087
  rb_gv_set("$VERBOSE", verbose);
@@ -1438,8 +1442,9 @@ static DumpFunc rails_funcs[] = {
1438
1442
  dump_array, // RUBY_T_ARRAY = 0x07,
1439
1443
  dump_hash, // RUBY_T_HASH = 0x08,
1440
1444
  dump_obj, // RUBY_T_STRUCT = 0x09,
1441
- oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
1442
- NULL, // RUBY_T_FILE = 0x0b,
1445
+ dump_bigdecimal, // RUBY_T_BIGNUM = 0x0a,
1446
+ //oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
1447
+ dump_as_string, // RUBY_T_FILE = 0x0b,
1443
1448
  dump_obj, // RUBY_T_DATA = 0x0c,
1444
1449
  NULL, // RUBY_T_MATCH = 0x0d,
1445
1450
  // Rails raises a stack error on Complex and Rational. It also corrupts