oj 3.7.11 → 3.9.1
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 +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
|
}
|