oj 3.7.12 → 3.8.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 +4 -4
- data/README.md +10 -2
- data/ext/oj/custom.c +15 -12
- data/ext/oj/dump.c +46 -26
- data/ext/oj/dump.h +2 -0
- data/ext/oj/dump_compat.c +13 -9
- data/ext/oj/mimic_json.c +7 -2
- data/ext/oj/oj.c +34 -24
- data/ext/oj/oj.h +6 -2
- data/ext/oj/parse.c +2 -1
- data/ext/oj/rails.c +8 -0
- data/ext/oj/sparse.c +2 -2
- data/ext/oj/string_writer.c +25 -3
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +3 -2
- data/pages/Options.md +19 -2
- data/pages/Security.md +1 -1
- data/test/bar.rb +25 -0
- data/test/foo.rb +160 -26
- data/test/test_custom.rb +99 -2
- data/test/test_various.rb +2 -0
- data/test/zoo.rb +13 -0
- metadata +71 -71
- data/test/big.rb +0 -15
- data/test/mem.rb +0 -35
data/ext/oj/oj.c
CHANGED
@@ -53,6 +53,7 @@ ID oj_length_id;
|
|
53
53
|
ID oj_new_id;
|
54
54
|
ID oj_parse_id;
|
55
55
|
ID oj_pos_id;
|
56
|
+
ID oj_raw_json_id;
|
56
57
|
ID oj_read_id;
|
57
58
|
ID oj_readpartial_id;
|
58
59
|
ID oj_replace_id;
|
@@ -94,6 +95,7 @@ VALUE oj_hash_class_sym;
|
|
94
95
|
VALUE oj_indent_sym;
|
95
96
|
VALUE oj_object_class_sym;
|
96
97
|
VALUE oj_quirks_mode_sym;
|
98
|
+
VALUE oj_safe_sym;
|
97
99
|
VALUE oj_trace_sym;
|
98
100
|
|
99
101
|
static VALUE allow_blank_sym;
|
@@ -137,6 +139,7 @@ static VALUE unicode_xss_sym;
|
|
137
139
|
static VALUE unix_sym;
|
138
140
|
static VALUE unix_zone_sym;
|
139
141
|
static VALUE use_as_json_sym;
|
142
|
+
static VALUE use_raw_json_sym;
|
140
143
|
static VALUE use_to_hash_sym;
|
141
144
|
static VALUE use_to_json_sym;
|
142
145
|
static VALUE wab_sym;
|
@@ -168,6 +171,7 @@ struct _options oj_default_options = {
|
|
168
171
|
No, // to_hash
|
169
172
|
No, // to_json
|
170
173
|
No, // as_json
|
174
|
+
No, // raw_json
|
171
175
|
No, // nilnil
|
172
176
|
Yes, // empty_string
|
173
177
|
Yes, // allow_gc
|
@@ -176,6 +180,7 @@ struct _options oj_default_options = {
|
|
176
180
|
No, // create_ok
|
177
181
|
Yes, // allow_nan
|
178
182
|
No, // trace
|
183
|
+
No, // safe
|
179
184
|
0, // integer_range_min
|
180
185
|
0, // integer_range_max
|
181
186
|
oj_json_class, // create_id
|
@@ -229,6 +234,7 @@ struct _options oj_default_options = {
|
|
229
234
|
* - *:float_precision* [_Fixnum_|_nil_] number of digits of precision when dumping floats, 0 indicates use Ruby
|
230
235
|
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false
|
231
236
|
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false
|
237
|
+
* - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false
|
232
238
|
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception
|
233
239
|
* - *:empty_string* [_Boolean_|_nil_] if true an empty input will not raise an Exception
|
234
240
|
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow)
|
@@ -245,8 +251,9 @@ struct _options oj_default_options = {
|
|
245
251
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
246
252
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
247
253
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
248
|
-
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
254
|
+
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
249
255
|
* - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
|
256
|
+
* - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is off)
|
250
257
|
*
|
251
258
|
* Return [_Hash_] all current option settings.
|
252
259
|
*/
|
@@ -269,6 +276,7 @@ get_def_opts(VALUE self) {
|
|
269
276
|
rb_hash_aset(opts, use_to_json_sym, (Yes == oj_default_options.to_json) ? Qtrue : ((No == oj_default_options.to_json) ? Qfalse : Qnil));
|
270
277
|
rb_hash_aset(opts, use_to_hash_sym, (Yes == oj_default_options.to_hash) ? Qtrue : ((No == oj_default_options.to_hash) ? Qfalse : Qnil));
|
271
278
|
rb_hash_aset(opts, use_as_json_sym, (Yes == oj_default_options.as_json) ? Qtrue : ((No == oj_default_options.as_json) ? Qfalse : Qnil));
|
279
|
+
rb_hash_aset(opts, use_raw_json_sym, (Yes == oj_default_options.raw_json) ? Qtrue : ((No == oj_default_options.raw_json) ? Qfalse : Qnil));
|
272
280
|
rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
|
273
281
|
rb_hash_aset(opts, empty_string_sym, (Yes == oj_default_options.empty_string) ? Qtrue : ((No == oj_default_options.empty_string) ? Qfalse : Qnil));
|
274
282
|
rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
|
@@ -276,6 +284,7 @@ get_def_opts(VALUE self) {
|
|
276
284
|
rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
|
277
285
|
rb_hash_aset(opts, oj_allow_nan_sym, (Yes == oj_default_options.allow_nan) ? Qtrue : ((No == oj_default_options.allow_nan) ? Qfalse : Qnil));
|
278
286
|
rb_hash_aset(opts, oj_trace_sym, (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
|
287
|
+
rb_hash_aset(opts, oj_safe_sym, (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
|
279
288
|
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
280
289
|
switch (oj_default_options.mode) {
|
281
290
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
@@ -287,7 +296,7 @@ get_def_opts(VALUE self) {
|
|
287
296
|
case WabMode: rb_hash_aset(opts, mode_sym, wab_sym); break;
|
288
297
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
289
298
|
}
|
290
|
-
|
299
|
+
|
291
300
|
if (oj_default_options.integer_range_max != 0 || oj_default_options.integer_range_min != 0) {
|
292
301
|
VALUE range = rb_obj_alloc(rb_cRange);
|
293
302
|
VALUE min = LONG2FIX(oj_default_options.integer_range_min);
|
@@ -343,7 +352,7 @@ get_def_opts(VALUE self) {
|
|
343
352
|
} else {
|
344
353
|
VALUE *vp;
|
345
354
|
volatile VALUE a = rb_ary_new();
|
346
|
-
|
355
|
+
|
347
356
|
for (vp = oj_default_options.ignore; Qnil != *vp; vp++) {
|
348
357
|
rb_ary_push(a, *vp);
|
349
358
|
}
|
@@ -374,6 +383,7 @@ get_def_opts(VALUE self) {
|
|
374
383
|
* - *:use_to_json* [_Boolean_|_nil_] call to_json() methods on dump, default is false.
|
375
384
|
* - *:use_as_json* [_Boolean_|_nil_] call as_json() methods on dump, default is false.
|
376
385
|
* - *:use_to_hash* [_Boolean_|_nil_] call to_hash() methods on dump, default is false.
|
386
|
+
* - *:use_raw_json* [_Boolean_|_nil_] call raw_json() methods on dump, default is false.
|
377
387
|
* - *:nilnil* [_Boolean_|_nil_] if true a nil input to load will return nil and not raise an Exception.
|
378
388
|
* - *:allow_gc* [_Boolean_|_nil_] allow or prohibit GC during parsing, default is true (allow).
|
379
389
|
* - *:quirks_mode* [_Boolean_|_nil_] allow single JSON values instead of documents, default is true (allow).
|
@@ -388,8 +398,9 @@ get_def_opts(VALUE self) {
|
|
388
398
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
|
389
399
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
|
390
400
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
391
|
-
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
401
|
+
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
392
402
|
* - *:trace* [_Boolean_] turn trace on or off.
|
403
|
+
* - *:safe* [_Boolean_] turn safe mimic on or off.
|
393
404
|
*/
|
394
405
|
static VALUE
|
395
406
|
set_def_opts(VALUE self, VALUE opts) {
|
@@ -410,6 +421,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
410
421
|
{ use_to_hash_sym, &copts->to_hash },
|
411
422
|
{ use_to_json_sym, &copts->to_json },
|
412
423
|
{ use_as_json_sym, &copts->as_json },
|
424
|
+
{ use_raw_json_sym, &copts->raw_json },
|
413
425
|
{ nilnil_sym, &copts->nilnil },
|
414
426
|
{ allow_blank_sym, &copts->nilnil }, // same as nilnil
|
415
427
|
{ empty_string_sym, &copts->empty_string },
|
@@ -418,13 +430,14 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
418
430
|
{ allow_invalid_unicode_sym, &copts->allow_invalid },
|
419
431
|
{ oj_allow_nan_sym, &copts->allow_nan },
|
420
432
|
{ oj_trace_sym, &copts->trace },
|
433
|
+
{ oj_safe_sym, &copts->safe },
|
421
434
|
{ oj_create_additions_sym, &copts->create_ok },
|
422
435
|
{ Qnil, 0 }
|
423
436
|
};
|
424
437
|
YesNoOpt o;
|
425
438
|
volatile VALUE v;
|
426
439
|
size_t len;
|
427
|
-
|
440
|
+
|
428
441
|
if (T_HASH != rb_type(ropts)) {
|
429
442
|
return;
|
430
443
|
}
|
@@ -715,7 +728,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
715
728
|
cnt = (int)RARRAY_LEN(v);
|
716
729
|
if (0 < cnt) {
|
717
730
|
int i;
|
718
|
-
|
731
|
+
|
719
732
|
copts->ignore = ALLOC_N(VALUE, cnt + 1);
|
720
733
|
for (i = 0; i < cnt; i++) {
|
721
734
|
copts->ignore[i] = rb_ary_entry(v, i);
|
@@ -802,11 +815,10 @@ oj_parse_opt_match_string(RxClass rc, VALUE ropts) {
|
|
802
815
|
*
|
803
816
|
* - *json* [_String_|_IO_] JSON String or an Object that responds to read()
|
804
817
|
* - *options* [_Hash_] load options (same as default_options)
|
805
|
-
* - -
|
806
818
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
807
819
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
808
820
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
809
|
-
*
|
821
|
+
*
|
810
822
|
* Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
|
811
823
|
*/
|
812
824
|
static VALUE
|
@@ -889,7 +901,6 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
889
901
|
*
|
890
902
|
* - *path* [_String_] to a file containing a JSON document
|
891
903
|
* - *options* [_Hash_] load options (same as default_options)
|
892
|
-
* - -
|
893
904
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
894
905
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
895
906
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
@@ -1064,7 +1075,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
1064
1075
|
* Dumps an Object (obj) to a string. If the object has a to_json method that
|
1065
1076
|
* will be called. The mode is set to :compat.
|
1066
1077
|
* - *obj* [_Object_] Object to serialize as an JSON document String
|
1067
|
-
* - *options* [_Hash_]
|
1078
|
+
* - *options* [_Hash_]
|
1068
1079
|
* - *:max_nesting* [_boolean_] It true nesting is limited to 100. The option to detect circular references is available but is not compatible with the json gem., default is false
|
1069
1080
|
* - *:allow_nan* [_boolean_] If true non JSON compliant words such as Nan and Infinity will be used as appropriate, default is true.
|
1070
1081
|
* - *:quirks_mode* [_boolean_] Allow single JSON values instead of documents, default is true (allow).
|
@@ -1126,7 +1137,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
|
|
1126
1137
|
static VALUE
|
1127
1138
|
to_file(int argc, VALUE *argv, VALUE self) {
|
1128
1139
|
struct _options copts = oj_default_options;
|
1129
|
-
|
1140
|
+
|
1130
1141
|
if (3 == argc) {
|
1131
1142
|
oj_parse_options(argv[2], &copts);
|
1132
1143
|
}
|
@@ -1149,7 +1160,7 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
1149
1160
|
static VALUE
|
1150
1161
|
to_stream(int argc, VALUE *argv, VALUE self) {
|
1151
1162
|
struct _options copts = oj_default_options;
|
1152
|
-
|
1163
|
+
|
1153
1164
|
if (3 == argc) {
|
1154
1165
|
oj_parse_options(argv[2], &copts);
|
1155
1166
|
}
|
@@ -1265,7 +1276,6 @@ register_odd_raw(int argc, VALUE *argv, VALUE self) {
|
|
1265
1276
|
*
|
1266
1277
|
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1267
1278
|
* - *options* [_Hash_] load options (same as default_options).
|
1268
|
-
* - -
|
1269
1279
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1270
1280
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1271
1281
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
@@ -1300,7 +1310,6 @@ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
|
|
1300
1310
|
*
|
1301
1311
|
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1302
1312
|
* - *options* [_Hash_] load options (same as default_options).
|
1303
|
-
* - -
|
1304
1313
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1305
1314
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1306
1315
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
@@ -1331,7 +1340,6 @@ extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
|
|
1331
1340
|
*
|
1332
1341
|
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1333
1342
|
* - *options* [_Hash_] load options (same as default_options).
|
1334
|
-
* - -
|
1335
1343
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1336
1344
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1337
1345
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
@@ -1367,7 +1375,6 @@ extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
|
|
1367
1375
|
*
|
1368
1376
|
* - *json* [_String_|_IO_] JSON String or an Object that responds to read().
|
1369
1377
|
* - *options* [_Hash_] load options (same as default_options).
|
1370
|
-
* - -
|
1371
1378
|
* - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
|
1372
1379
|
* - *start* [_optional, _Integer_] start position of parsed JSON for obj.
|
1373
1380
|
* - *len* [_optional, _Integer_] length of parsed JSON for obj.
|
@@ -1429,16 +1436,16 @@ extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
1429
1436
|
|
1430
1437
|
/* Document-method: generate
|
1431
1438
|
* call-seq: generate(obj, opts=nil)
|
1432
|
-
*
|
1439
|
+
*
|
1433
1440
|
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
1434
1441
|
* respond to to_h or to_json. Options other than those listed such as
|
1435
1442
|
* +:allow_nan+ or +:max_nesting+ are ignored.
|
1436
|
-
*
|
1443
|
+
*
|
1437
1444
|
* - *obj* [_Object__|_Hash_|_Array_] object to convert to a JSON String
|
1438
1445
|
* - *opts* [_Hash_] options
|
1439
|
-
*
|
1446
|
+
* - *:indent* [_String_] String to use for indentation.
|
1440
1447
|
* - *:space* [_String_] String placed after a , or : delimiter
|
1441
|
-
* - *:
|
1448
|
+
* - *:space_before* [_String_] String placed before a : delimiter
|
1442
1449
|
* - *:object_nl* [_String_] String placed after a JSON object
|
1443
1450
|
* - *:array_nl* [_String_] String placed after a JSON array
|
1444
1451
|
* - *:ascii_only* [_Boolean_] if not nil or false then use only ascii characters in the output. Note JSON.generate does support this even if it is not documented.
|
@@ -1481,15 +1488,15 @@ protect_require(VALUE x) {
|
|
1481
1488
|
* modes are:
|
1482
1489
|
*
|
1483
1490
|
* - *:strict* mode will only allow the 7 basic JSON types to be serialized. Any other Object
|
1484
|
-
* will raise an Exception.
|
1485
|
-
*
|
1491
|
+
* will raise an Exception.
|
1492
|
+
*
|
1486
1493
|
* - *:null* mode is similar to the :strict mode except any Object that is not
|
1487
1494
|
* one of the JSON base types is replaced by a JSON null.
|
1488
|
-
*
|
1495
|
+
*
|
1489
1496
|
* - *:object* mode will dump any Object as a JSON Object with keys that match
|
1490
1497
|
* the Ruby Object's variable names without the '@' character. This is the
|
1491
1498
|
* highest performance mode.
|
1492
|
-
*
|
1499
|
+
*
|
1493
1500
|
* - *:compat* or *:json* mode is the compatible mode for the json gem. It mimics
|
1494
1501
|
* the json gem including the options, defaults, and restrictions.
|
1495
1502
|
*
|
@@ -1575,6 +1582,7 @@ Init_oj() {
|
|
1575
1582
|
oj_new_id = rb_intern("new");
|
1576
1583
|
oj_parse_id = rb_intern("parse");
|
1577
1584
|
oj_pos_id = rb_intern("pos");
|
1585
|
+
oj_raw_json_id = rb_intern("raw_json");
|
1578
1586
|
oj_read_id = rb_intern("read");
|
1579
1587
|
oj_readpartial_id = rb_intern("readpartial");
|
1580
1588
|
oj_replace_id = rb_intern("replace");
|
@@ -1651,6 +1659,7 @@ Init_oj() {
|
|
1651
1659
|
oj_object_class_sym = ID2SYM(rb_intern("object_class")); rb_gc_register_address(&oj_object_class_sym);
|
1652
1660
|
oj_object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&oj_object_nl_sym);
|
1653
1661
|
oj_quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&oj_quirks_mode_sym);
|
1662
|
+
oj_safe_sym = ID2SYM(rb_intern("safe")); rb_gc_register_address(&oj_safe_sym);
|
1654
1663
|
oj_space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&oj_space_before_sym);
|
1655
1664
|
oj_space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&oj_space_sym);
|
1656
1665
|
oj_trace_sym = ID2SYM(rb_intern("trace")); rb_gc_register_address(&oj_trace_sym);
|
@@ -1666,6 +1675,7 @@ Init_oj() {
|
|
1666
1675
|
unix_sym = ID2SYM(rb_intern("unix")); rb_gc_register_address(&unix_sym);
|
1667
1676
|
unix_zone_sym = ID2SYM(rb_intern("unix_zone")); rb_gc_register_address(&unix_zone_sym);
|
1668
1677
|
use_as_json_sym = ID2SYM(rb_intern("use_as_json")); rb_gc_register_address(&use_as_json_sym);
|
1678
|
+
use_raw_json_sym = ID2SYM(rb_intern("use_raw_json")); rb_gc_register_address(&use_raw_json_sym);
|
1669
1679
|
use_to_hash_sym = ID2SYM(rb_intern("use_to_hash")); rb_gc_register_address(&use_to_hash_sym);
|
1670
1680
|
use_to_json_sym = ID2SYM(rb_intern("use_to_json")); rb_gc_register_address(&use_to_json_sym);
|
1671
1681
|
wab_sym = ID2SYM(rb_intern("wab")); rb_gc_register_address(&wab_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -139,6 +139,7 @@ typedef struct _options {
|
|
139
139
|
char to_hash; // YesNo
|
140
140
|
char to_json; // YesNo
|
141
141
|
char as_json; // YesNo
|
142
|
+
char raw_json; // YesNo
|
142
143
|
char nilnil; // YesNo
|
143
144
|
char empty_string; // YesNo
|
144
145
|
char allow_gc; // allow GC during parse
|
@@ -147,6 +148,7 @@ typedef struct _options {
|
|
147
148
|
char create_ok; // YesNo allow create_id
|
148
149
|
char allow_nan; // YEsyNo for parsing only
|
149
150
|
char trace; // YesNo
|
151
|
+
char safe; // YesNo
|
150
152
|
int64_t integer_range_min; // dump numbers outside range as string
|
151
153
|
int64_t integer_range_max;
|
152
154
|
const char *create_id; // 0 or string
|
@@ -202,7 +204,7 @@ typedef struct _strWriter {
|
|
202
204
|
char *types; // DumpType
|
203
205
|
char *types_end;
|
204
206
|
int keyWritten;
|
205
|
-
|
207
|
+
|
206
208
|
} *StrWriter;
|
207
209
|
|
208
210
|
typedef struct _streamWriter {
|
@@ -219,7 +221,7 @@ enum {
|
|
219
221
|
COL_VAL = 0x02,
|
220
222
|
RUBY_VAL = 0x03
|
221
223
|
};
|
222
|
-
|
224
|
+
|
223
225
|
typedef struct _leaf {
|
224
226
|
struct _leaf *next;
|
225
227
|
union {
|
@@ -349,6 +351,7 @@ extern ID oj_readpartial_id;
|
|
349
351
|
extern ID oj_replace_id;
|
350
352
|
extern ID oj_stat_id;
|
351
353
|
extern ID oj_string_id;
|
354
|
+
extern ID oj_raw_json_id;
|
352
355
|
extern ID oj_to_h_id;
|
353
356
|
extern ID oj_to_hash_id;
|
354
357
|
extern ID oj_to_json_id;
|
@@ -365,6 +368,7 @@ extern ID oj_write_id;
|
|
365
368
|
|
366
369
|
extern bool oj_use_hash_alt;
|
367
370
|
extern bool oj_use_array_alt;
|
371
|
+
extern bool string_writer_optimized;
|
368
372
|
|
369
373
|
#if HAVE_LIBPTHREAD
|
370
374
|
extern pthread_mutex_t oj_cache_mutex;
|
data/ext/oj/parse.c
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include <string.h>
|
9
9
|
#include <unistd.h>
|
10
10
|
#include <math.h>
|
11
|
+
#include <ruby/util.h>
|
11
12
|
|
12
13
|
#include "oj.h"
|
13
14
|
#include "encode.h"
|
@@ -1036,7 +1037,7 @@ CLEANUP:
|
|
1036
1037
|
if (Qnil != pi->err_class) {
|
1037
1038
|
pi->err.clas = pi->err_class;
|
1038
1039
|
}
|
1039
|
-
if (CompatMode == pi->options.mode) {
|
1040
|
+
if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
|
1040
1041
|
// The json gem requires the error message be UTF-8 encoded. In
|
1041
1042
|
// additional the complete JSON source must be returned. There
|
1042
1043
|
// does not seem to be a size limit.
|
data/ext/oj/rails.c
CHANGED
@@ -750,6 +750,8 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
|
750
750
|
oj_rails_array_opt = on;
|
751
751
|
} else if (rb_cFloat == *argv) {
|
752
752
|
oj_rails_float_opt = on;
|
753
|
+
} else if (oj_string_writer_class == *argv) {
|
754
|
+
string_writer_optimized = on;
|
753
755
|
} else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) ||
|
754
756
|
NULL != (ro = create_opt(rot, *argv))) {
|
755
757
|
ro->on = on;
|
@@ -793,6 +795,7 @@ encoder_optimize(int argc, VALUE *argv, VALUE self) {
|
|
793
795
|
static VALUE
|
794
796
|
rails_optimize(int argc, VALUE *argv, VALUE self) {
|
795
797
|
optimize(argc, argv, &ropts, true);
|
798
|
+
string_writer_optimized = true;
|
796
799
|
|
797
800
|
return Qnil;
|
798
801
|
}
|
@@ -844,6 +847,7 @@ encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
844
847
|
static VALUE
|
845
848
|
rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
846
849
|
optimize(argc, argv, &ropts, false);
|
850
|
+
string_writer_optimized = false;
|
847
851
|
|
848
852
|
return Qnil;
|
849
853
|
}
|
@@ -1401,6 +1405,8 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1401
1405
|
|
1402
1406
|
if (NULL != (ro = oj_rails_get_opt(out->ropts, rb_obj_class(obj))) && ro->on) {
|
1403
1407
|
ro->dump(obj, depth, out, as_ok);
|
1408
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1409
|
+
oj_dump_raw_json(obj, depth, out);
|
1404
1410
|
} else if (rb_respond_to(obj, oj_as_json_id)) {
|
1405
1411
|
dump_as_json(obj, depth, out, true);
|
1406
1412
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
@@ -1408,6 +1414,8 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1408
1414
|
} else {
|
1409
1415
|
oj_dump_obj_to_s(obj, out);
|
1410
1416
|
}
|
1417
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1418
|
+
oj_dump_raw_json(obj, depth, out);
|
1411
1419
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1412
1420
|
// Always attempt to_hash.
|
1413
1421
|
dump_to_hash(obj, depth, out);
|
data/ext/oj/sparse.c
CHANGED
@@ -632,7 +632,7 @@ oj_sparse2(ParseInfo pi) {
|
|
632
632
|
while (1) {
|
633
633
|
if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
|
634
634
|
VALUE err_clas = oj_get_json_err_class("NestingError");
|
635
|
-
|
635
|
+
|
636
636
|
oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
|
637
637
|
pi->err_class = err_clas;
|
638
638
|
return;
|
@@ -890,7 +890,7 @@ CLEANUP:
|
|
890
890
|
if (Qnil != pi->err_class && 0 != pi->err_class) {
|
891
891
|
pi->err.clas = pi->err_class;
|
892
892
|
}
|
893
|
-
if (CompatMode == pi->options.mode) {
|
893
|
+
if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
|
894
894
|
// The json gem requires the error message be UTF-8 encoded. In
|
895
895
|
// additional the complete JSON source should be returned but that
|
896
896
|
// is not possible without stored all the bytes read and reading
|
data/ext/oj/string_writer.c
CHANGED
@@ -8,6 +8,8 @@
|
|
8
8
|
|
9
9
|
extern VALUE Oj;
|
10
10
|
|
11
|
+
bool string_writer_optimized = false;
|
12
|
+
|
11
13
|
static void
|
12
14
|
key_check(StrWriter sw, const char *key) {
|
13
15
|
DumpType type = sw->types[sw->depth];
|
@@ -152,7 +154,7 @@ oj_str_writer_push_array(StrWriter sw, const char *key) {
|
|
152
154
|
void
|
153
155
|
oj_str_writer_push_value(StrWriter sw, VALUE val, const char *key) {
|
154
156
|
Out out = &sw->out;
|
155
|
-
|
157
|
+
|
156
158
|
if (sw->keyWritten) {
|
157
159
|
sw->keyWritten = 0;
|
158
160
|
} else {
|
@@ -273,7 +275,7 @@ str_writer_free(void *ptr) {
|
|
273
275
|
static VALUE
|
274
276
|
str_writer_new(int argc, VALUE *argv, VALUE self) {
|
275
277
|
StrWriter sw = ALLOC(struct _strWriter);
|
276
|
-
|
278
|
+
|
277
279
|
oj_str_writer_init(sw, 0);
|
278
280
|
if (1 == argc) {
|
279
281
|
oj_parse_options(argv[0], &sw->opts);
|
@@ -487,8 +489,26 @@ str_writer_to_s(VALUE self) {
|
|
487
489
|
return oj_encode(rstr);
|
488
490
|
}
|
489
491
|
|
492
|
+
/* Document-method: as_json
|
493
|
+
* call-seq: as_json()
|
494
|
+
*
|
495
|
+
* Returns the contents of the writer as a JSON element. If called from inside
|
496
|
+
* an array or hash by Oj the raw buffer will be used othersize a more
|
497
|
+
* inefficient parse of the contents and a return of the result is
|
498
|
+
* completed. The parse uses the trict mode.
|
499
|
+
*
|
500
|
+
* *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
|
501
|
+
*/
|
502
|
+
static VALUE
|
503
|
+
str_writer_as_json(VALUE self) {
|
504
|
+
if (string_writer_optimized) {
|
505
|
+
return self;
|
506
|
+
}
|
507
|
+
return rb_hash_new();
|
508
|
+
}
|
509
|
+
|
490
510
|
/* Document-class: Oj::StringWriter
|
491
|
-
*
|
511
|
+
*
|
492
512
|
* Supports building a JSON document one element at a time. Build the document
|
493
513
|
* by pushing values into the document. Pushing an array or an object will
|
494
514
|
* create that element in the JSON document and subsequent pushes will add the
|
@@ -509,4 +529,6 @@ oj_string_writer_init() {
|
|
509
529
|
rb_define_method(oj_string_writer_class, "pop_all", str_writer_pop_all, 0);
|
510
530
|
rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
|
511
531
|
rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
|
532
|
+
rb_define_method(oj_string_writer_class, "raw_json", str_writer_to_s, 0);
|
533
|
+
rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, 0);
|
512
534
|
}
|