oj 3.7.12 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- * - - *:indent* [_String_] String to use for indentation.
1446
+ * - *:indent* [_String_] String to use for indentation.
1440
1447
  * - *:space* [_String_] String placed after a , or : delimiter
1441
- * - *:space * _before [_String_] String placed before a : delimiter
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);
@@ -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;
@@ -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.
@@ -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);
@@ -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
@@ -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
  }