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 +4 -4
- data/README.md +2 -2
- data/ext/oj/custom.c +2 -0
- data/ext/oj/dump.c +9 -12
- data/ext/oj/dump_compat.c +6 -9
- data/ext/oj/dump_object.c +14 -9
- data/ext/oj/mimic_json.c +4 -2
- data/ext/oj/oj.c +44 -27
- data/ext/oj/oj.h +4 -2
- data/ext/oj/parse.c +12 -3
- data/ext/oj/parse.h +1 -0
- data/ext/oj/rails.c +7 -2
- data/ext/oj/sparse.c +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Rails.md +21 -21
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +8 -11
- data/test/baz.rb +16 -0
- data/test/foo.rb +154 -8
- data/test/test_compat.rb +0 -7
- data/test/test_custom.rb +6 -2
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +4 -3
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +41 -62
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62a52be7754c5ef34c3006fb28fa918cb18f23c26ffa94e8daedf05396bbe0fb
|
4
|
+
data.tar.gz: 9cf9cfab00cf1e28f8b42c6d3e88ee6a2a785093cc024c558eeceb25eaf39cd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/ext/oj/custom.c
CHANGED
@@ -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;
|
data/ext/oj/dump.c
CHANGED
@@ -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->
|
1027
|
-
(out->opts->
|
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
|
-
|
1065
|
+
bool dump_as_string = false;
|
1066
1066
|
|
1067
|
-
|
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
|
-
|
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
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
|
data/ext/oj/dump_object.c
CHANGED
@@ -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
|
}
|
data/ext/oj/mimic_json.c
CHANGED
@@ -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
|
-
|
694
|
-
|
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
|
data/ext/oj/oj.c
CHANGED
@@ -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
|
-
|
185
|
-
|
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.
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
else {
|
309
|
-
|
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
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
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);
|
data/ext/oj/oj.h
CHANGED
@@ -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
|
-
|
153
|
-
|
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
|
data/ext/oj/parse.c
CHANGED
@@ -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::
|
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));
|
data/ext/oj/parse.h
CHANGED
@@ -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);
|
data/ext/oj/rails.c
CHANGED
@@ -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
|
-
|
1442
|
-
|
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
|