oj 3.7.11 → 3.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -2
- data/ext/oj/custom.c +74 -48
- 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/extconf.rb +1 -0
- data/ext/oj/mimic_json.c +7 -2
- data/ext/oj/object.c +8 -5
- data/ext/oj/oj.c +37 -27
- data/ext/oj/oj.h +8 -4
- data/ext/oj/parse.c +2 -1
- data/ext/oj/rails.c +41 -28
- data/ext/oj/resolve.c +3 -3
- data/ext/oj/sparse.c +2 -2
- data/ext/oj/string_writer.c +25 -3
- data/ext/oj/val_stack.c +9 -9
- data/ext/oj/val_stack.h +9 -9
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +3 -2
- data/pages/Options.md +23 -2
- data/pages/Security.md +1 -1
- data/test/test_custom.rb +99 -2
- data/test/test_various.rb +2 -0
- metadata +4 -4
data/ext/oj/oj.h
CHANGED
@@ -21,7 +21,7 @@ extern "C" {
|
|
21
21
|
#include <stdint.h>
|
22
22
|
#include <stdbool.h>
|
23
23
|
|
24
|
-
#
|
24
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
25
25
|
#include <pthread.h>
|
26
26
|
#endif
|
27
27
|
#include "cache8.h"
|
@@ -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,8 +368,9 @@ 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
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
370
374
|
extern pthread_mutex_t oj_cache_mutex;
|
371
375
|
#else
|
372
376
|
extern VALUE 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
@@ -117,7 +117,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
117
117
|
dump_rails_val(value, depth, out, true);
|
118
118
|
out->depth = depth;
|
119
119
|
*out->cur++ = ',';
|
120
|
-
|
120
|
+
|
121
121
|
return ST_CONTINUE;
|
122
122
|
}
|
123
123
|
|
@@ -230,7 +230,7 @@ dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
|
|
230
230
|
int tzhour, tzmin;
|
231
231
|
char tzsign = '+';
|
232
232
|
int len;
|
233
|
-
|
233
|
+
|
234
234
|
if (out->end - out->cur <= 36) {
|
235
235
|
assure_size(out, 36);
|
236
236
|
}
|
@@ -353,7 +353,7 @@ columns_array(VALUE rcols, int *ccnt) {
|
|
353
353
|
StrLen cols;
|
354
354
|
int i;
|
355
355
|
int cnt = (int)RARRAY_LEN(rcols);
|
356
|
-
|
356
|
+
|
357
357
|
*ccnt = cnt;
|
358
358
|
cols = ALLOC_N(struct _strLen, cnt);
|
359
359
|
for (i = 0, cp = cols; i < cnt; i++, cp++) {
|
@@ -372,7 +372,7 @@ dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
|
|
372
372
|
size_t size;
|
373
373
|
int d2 = depth + 1;
|
374
374
|
int i;
|
375
|
-
|
375
|
+
|
376
376
|
assure_size(out, 2);
|
377
377
|
*out->cur++ = '{';
|
378
378
|
size = depth * out->indent + 3;
|
@@ -432,7 +432,7 @@ dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok) {
|
|
432
432
|
int i, rcnt;
|
433
433
|
size_t size;
|
434
434
|
int d2 = depth + 1;
|
435
|
-
|
435
|
+
|
436
436
|
if (0 == rows_id) {
|
437
437
|
rows_id = rb_intern("@rows");
|
438
438
|
columns_id = rb_intern("@columns");
|
@@ -597,7 +597,7 @@ create_opt(ROptTable rot, VALUE clas) {
|
|
597
597
|
ro = &rot->table[olen];
|
598
598
|
} else {
|
599
599
|
int i;
|
600
|
-
|
600
|
+
|
601
601
|
for (i = 0, ro = rot->table; i < olen; i++, ro++) {
|
602
602
|
if (clas < ro->clas) {
|
603
603
|
memmove(ro + 1, ro, sizeof(struct _rOpt) * (olen - i));
|
@@ -672,7 +672,7 @@ encoder_new(int argc, VALUE *argv, VALUE self) {
|
|
672
672
|
e->opts = oj_default_options;
|
673
673
|
e->arg = Qnil;
|
674
674
|
copy_opts(&ropts, &e->ropts);
|
675
|
-
|
675
|
+
|
676
676
|
if (1 <= argc && Qnil != *argv) {
|
677
677
|
oj_parse_options(*argv, &e->opts);
|
678
678
|
e->arg = *argv;
|
@@ -727,7 +727,7 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
|
727
727
|
int i;
|
728
728
|
NamedFunc nf;
|
729
729
|
VALUE clas;
|
730
|
-
|
730
|
+
|
731
731
|
oj_rails_hash_opt = on;
|
732
732
|
oj_rails_array_opt = on;
|
733
733
|
oj_rails_float_opt = on;
|
@@ -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;
|
@@ -759,14 +761,14 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
|
759
761
|
|
760
762
|
/* Document-method optimize
|
761
763
|
* call-seq: optimize(*classes)
|
762
|
-
*
|
764
|
+
*
|
763
765
|
* Use Oj rails optimized routines to encode the specified classes. This
|
764
766
|
* ignores the as_json() method on the class and uses an internal encoding
|
765
767
|
* instead. Passing in no classes indicates all should use the optimized
|
766
768
|
* version of encoding for all previously optimized classes. Passing in the
|
767
769
|
* Object class set a global switch that will then use the optimized behavior
|
768
770
|
* for all classes.
|
769
|
-
*
|
771
|
+
*
|
770
772
|
* - *classes* [_Class_] a list of classes to optimize
|
771
773
|
*/
|
772
774
|
static VALUE
|
@@ -780,19 +782,20 @@ encoder_optimize(int argc, VALUE *argv, VALUE self) {
|
|
780
782
|
|
781
783
|
/* Document-method: optimize
|
782
784
|
* call-seq: optimize(*classes)
|
783
|
-
*
|
785
|
+
*
|
784
786
|
* Use Oj rails optimized routines to encode the specified classes. This
|
785
787
|
* ignores the as_json() method on the class and uses an internal encoding
|
786
788
|
* instead. Passing in no classes indicates all should use the optimized
|
787
789
|
* version of encoding for all previously optimized classes. Passing in the
|
788
790
|
* Object class set a global switch that will then use the optimized behavior
|
789
791
|
* for all classes.
|
790
|
-
*
|
792
|
+
*
|
791
793
|
* - *classes* [_Class_] a list of classes to optimize
|
792
794
|
*/
|
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
|
}
|
@@ -806,7 +809,7 @@ rails_optimize(int argc, VALUE *argv, VALUE self) {
|
|
806
809
|
VALUE
|
807
810
|
rails_mimic_json(VALUE self) {
|
808
811
|
VALUE json;
|
809
|
-
|
812
|
+
|
810
813
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
811
814
|
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
812
815
|
} else {
|
@@ -820,7 +823,7 @@ rails_mimic_json(VALUE self) {
|
|
820
823
|
|
821
824
|
/* Document-method: deoptimize
|
822
825
|
* call-seq: deoptimize(*classes)
|
823
|
-
*
|
826
|
+
*
|
824
827
|
* Turn off Oj rails optimization on the specified classes.
|
825
828
|
*
|
826
829
|
* - *classes* [_Class_] a list of classes to deoptimize
|
@@ -836,7 +839,7 @@ encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
836
839
|
|
837
840
|
/* Document-method: deoptimize
|
838
841
|
* call-seq: deoptimize(*classes)
|
839
|
-
*
|
842
|
+
*
|
840
843
|
* Turn off Oj rails optimization on the specified classes.
|
841
844
|
*
|
842
845
|
* - *classes* [_Class_] a list of classes to deoptimize
|
@@ -844,13 +847,14 @@ 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
|
}
|
850
854
|
|
851
855
|
/* Document-method:optimized?
|
852
856
|
* call-seq: optimized?(clas)
|
853
|
-
*
|
857
|
+
*
|
854
858
|
* - *clas* [_Class_] Class to check
|
855
859
|
*
|
856
860
|
* @return true if the class is being optimized for rails and false otherwise
|
@@ -868,7 +872,7 @@ encoder_optimized(VALUE self, VALUE clas) {
|
|
868
872
|
|
869
873
|
/* Document-method: optimized?
|
870
874
|
* call-seq: optimized?(clas)
|
871
|
-
*
|
875
|
+
*
|
872
876
|
* Returns true if the specified Class is being optimized.
|
873
877
|
*/
|
874
878
|
static VALUE
|
@@ -966,7 +970,7 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
|
966
970
|
|
967
971
|
/* Document-method: encode
|
968
972
|
* call-seq: encode(obj)
|
969
|
-
*
|
973
|
+
*
|
970
974
|
* - *obj* [_Object_] object to encode
|
971
975
|
*
|
972
976
|
* Returns encoded object as a JSON string.
|
@@ -977,7 +981,7 @@ encoder_encode(VALUE self, VALUE obj) {
|
|
977
981
|
|
978
982
|
if (Qnil != e->arg) {
|
979
983
|
VALUE argv[1] = { e->arg };
|
980
|
-
|
984
|
+
|
981
985
|
return encode(obj, &e->ropts, &e->opts, 1, argv);
|
982
986
|
}
|
983
987
|
return encode(obj, &e->ropts, &e->opts, 0, NULL);
|
@@ -985,9 +989,9 @@ encoder_encode(VALUE self, VALUE obj) {
|
|
985
989
|
|
986
990
|
/* Document-method: encode
|
987
991
|
* call-seq: encode(obj, opts=nil)
|
988
|
-
*
|
992
|
+
*
|
989
993
|
* Encode obj as a JSON String.
|
990
|
-
*
|
994
|
+
*
|
991
995
|
* - *obj* [_Object_|Hash|Array] object to convert to a JSON String
|
992
996
|
* - *opts* [_Hash_] options
|
993
997
|
*
|
@@ -1037,7 +1041,7 @@ rails_time_precision(VALUE self, VALUE prec) {
|
|
1037
1041
|
|
1038
1042
|
/* Document-method: set_encoder
|
1039
1043
|
* call-seq: set_encoder()
|
1040
|
-
*
|
1044
|
+
*
|
1041
1045
|
* Sets the ActiveSupport.encoder to Oj::Rails::Encoder and wraps some of the
|
1042
1046
|
* formatting globals used by ActiveSupport to allow the use of those globals
|
1043
1047
|
* in the Oj::Rails optimizations.
|
@@ -1049,7 +1053,7 @@ rails_set_encoder(VALUE self) {
|
|
1049
1053
|
VALUE encoding;
|
1050
1054
|
VALUE pv;
|
1051
1055
|
VALUE verbose;
|
1052
|
-
|
1056
|
+
|
1053
1057
|
if (rb_const_defined_at(rb_cObject, rb_intern("ActiveSupport"))) {
|
1054
1058
|
active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
|
1055
1059
|
} else {
|
@@ -1067,6 +1071,8 @@ rails_set_encoder(VALUE self) {
|
|
1067
1071
|
rb_undef_method(encoding, "use_standard_json_time_format=");
|
1068
1072
|
rb_define_module_function(encoding, "use_standard_json_time_format=", rails_use_standard_json_time_format, 1);
|
1069
1073
|
|
1074
|
+
pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
|
1075
|
+
escape_html = Qtrue == pv;
|
1070
1076
|
rb_undef_method(encoding, "escape_html_entities_in_json=");
|
1071
1077
|
rb_define_module_function(encoding, "escape_html_entities_in_json=", rails_escape_html_entities_in_json, 1);
|
1072
1078
|
|
@@ -1090,7 +1096,7 @@ rails_set_decoder(VALUE self) {
|
|
1090
1096
|
VALUE json;
|
1091
1097
|
VALUE json_error;
|
1092
1098
|
VALUE verbose;
|
1093
|
-
|
1099
|
+
|
1094
1100
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
1095
1101
|
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
1096
1102
|
} else {
|
@@ -1113,7 +1119,7 @@ rails_set_decoder(VALUE self) {
|
|
1113
1119
|
rb_undef_method(json, "parse");
|
1114
1120
|
rb_define_module_function(json, "parse", oj_mimic_parse, -1);
|
1115
1121
|
rb_gv_set("$VERBOSE", verbose);
|
1116
|
-
|
1122
|
+
|
1117
1123
|
return Qnil;
|
1118
1124
|
}
|
1119
1125
|
|
@@ -1133,7 +1139,7 @@ oj_optimize_rails(VALUE self) {
|
|
1133
1139
|
}
|
1134
1140
|
|
1135
1141
|
/* Document-module: Oj::Rails
|
1136
|
-
*
|
1142
|
+
*
|
1137
1143
|
* Module that provides rails and active support compatibility.
|
1138
1144
|
*/
|
1139
1145
|
/* Document-class: Oj::Rails::Encoder
|
@@ -1143,7 +1149,7 @@ oj_optimize_rails(VALUE self) {
|
|
1143
1149
|
void
|
1144
1150
|
oj_mimic_rails_init() {
|
1145
1151
|
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1146
|
-
|
1152
|
+
|
1147
1153
|
rb_define_module_function(rails, "encode", rails_encode, -1);
|
1148
1154
|
|
1149
1155
|
encoder_class = rb_define_class_under(rails, "Encoder", rb_cObject);
|
@@ -1283,7 +1289,10 @@ hash_cb(VALUE key, VALUE value, Out out) {
|
|
1283
1289
|
int depth = out->depth;
|
1284
1290
|
long size;
|
1285
1291
|
int rtype = rb_type(key);
|
1286
|
-
|
1292
|
+
|
1293
|
+
if (out->omit_nil && Qnil == value) {
|
1294
|
+
return ST_CONTINUE;
|
1295
|
+
}
|
1287
1296
|
if (rtype != T_STRING && rtype != T_SYMBOL) {
|
1288
1297
|
key = rb_funcall(key, oj_to_s_id, 0);
|
1289
1298
|
rtype = rb_type(key);
|
@@ -1398,6 +1407,8 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1398
1407
|
|
1399
1408
|
if (NULL != (ro = oj_rails_get_opt(out->ropts, rb_obj_class(obj))) && ro->on) {
|
1400
1409
|
ro->dump(obj, depth, out, as_ok);
|
1410
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1411
|
+
oj_dump_raw_json(obj, depth, out);
|
1401
1412
|
} else if (rb_respond_to(obj, oj_as_json_id)) {
|
1402
1413
|
dump_as_json(obj, depth, out, true);
|
1403
1414
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
@@ -1405,6 +1416,8 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1405
1416
|
} else {
|
1406
1417
|
oj_dump_obj_to_s(obj, out);
|
1407
1418
|
}
|
1419
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1420
|
+
oj_dump_raw_json(obj, depth, out);
|
1408
1421
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1409
1422
|
// Always attempt to_hash.
|
1410
1423
|
dump_to_hash(obj, depth, out);
|
data/ext/oj/resolve.c
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
#include <stdlib.h>
|
7
7
|
#include <stdio.h>
|
8
8
|
#include <string.h>
|
9
|
-
#
|
9
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
10
10
|
#include <pthread.h>
|
11
11
|
#endif
|
12
12
|
|
@@ -75,7 +75,7 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
|
|
75
75
|
if (No == pi->options.class_cache) {
|
76
76
|
return resolve_classpath(pi, name, len, auto_define, error_class);
|
77
77
|
}
|
78
|
-
#
|
78
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
79
79
|
pthread_mutex_lock(&oj_cache_mutex);
|
80
80
|
#else
|
81
81
|
rb_mutex_lock(oj_cache_mutex);
|
@@ -85,7 +85,7 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
|
|
85
85
|
*slot = clas;
|
86
86
|
}
|
87
87
|
}
|
88
|
-
#
|
88
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
89
89
|
pthread_mutex_unlock(&oj_cache_mutex);
|
90
90
|
#else
|
91
91
|
rb_mutex_unlock(oj_cache_mutex);
|
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
|
}
|