@@ -12,6 +12,7 @@ typedef struct JSON_Generator_StateStruct {
12
12
VALUE space_before ;
13
13
VALUE object_nl ;
14
14
VALUE array_nl ;
15
+ VALUE as_json ;
15
16
16
17
long max_nesting ;
17
18
long depth ;
@@ -30,8 +31,8 @@ typedef struct JSON_Generator_StateStruct {
30
31
static VALUE mJSON , cState , cFragment , mString_Extend , eGeneratorError , eNestingError , Encoding_UTF_8 ;
31
32
32
33
static ID i_to_s , i_to_json , i_new , i_pack , i_unpack , i_create_id , i_extend , i_encode ;
33
- static ID sym_indent , sym_space , sym_space_before , sym_object_nl , sym_array_nl , sym_max_nesting , sym_allow_nan ,
34
- sym_ascii_only , sym_depth , sym_buffer_initial_length , sym_script_safe , sym_escape_slash , sym_strict ;
34
+ static VALUE sym_indent , sym_space , sym_space_before , sym_object_nl , sym_array_nl , sym_max_nesting , sym_allow_nan ,
35
+ sym_ascii_only , sym_depth , sym_buffer_initial_length , sym_script_safe , sym_escape_slash , sym_strict , sym_as_json ;
35
36
36
37
37
38
#define GET_STATE_TO (self , state ) \
@@ -648,6 +649,7 @@ static void State_mark(void *ptr)
648
649
rb_gc_mark_movable (state -> space_before );
649
650
rb_gc_mark_movable (state -> object_nl );
650
651
rb_gc_mark_movable (state -> array_nl );
652
+ rb_gc_mark_movable (state -> as_json );
651
653
}
652
654
653
655
static void State_compact (void * ptr )
@@ -658,6 +660,7 @@ static void State_compact(void *ptr)
658
660
state -> space_before = rb_gc_location (state -> space_before );
659
661
state -> object_nl = rb_gc_location (state -> object_nl );
660
662
state -> array_nl = rb_gc_location (state -> array_nl );
663
+ state -> as_json = rb_gc_location (state -> as_json );
661
664
}
662
665
663
666
static void State_free (void * ptr )
@@ -714,6 +717,7 @@ static void vstate_spill(struct generate_json_data *data)
714
717
RB_OBJ_WRITTEN (vstate , Qundef , state -> space_before );
715
718
RB_OBJ_WRITTEN (vstate , Qundef , state -> object_nl );
716
719
RB_OBJ_WRITTEN (vstate , Qundef , state -> array_nl );
720
+ RB_OBJ_WRITTEN (vstate , Qundef , state -> as_json );
717
721
}
718
722
719
723
static inline VALUE vstate_get (struct generate_json_data * data )
@@ -982,6 +986,8 @@ static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *d
982
986
static void generate_json (FBuffer * buffer , struct generate_json_data * data , JSON_Generator_State * state , VALUE obj )
983
987
{
984
988
VALUE tmp ;
989
+ bool as_json_called = false;
990
+ start :
985
991
if (obj == Qnil ) {
986
992
generate_json_null (buffer , data , state , obj );
987
993
} else if (obj == Qfalse ) {
@@ -1025,7 +1031,13 @@ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON
1025
1031
default :
1026
1032
general :
1027
1033
if (state -> strict ) {
1028
- raise_generator_error (obj , "%" PRIsVALUE " not allowed in JSON" , CLASS_OF (obj ));
1034
+ if (RTEST (state -> as_json ) && !as_json_called ) {
1035
+ obj = rb_proc_call_with_block (state -> as_json , 1 , & obj , Qnil );
1036
+ as_json_called = true;
1037
+ goto start ;
1038
+ } else {
1039
+ raise_generator_error (obj , "%" PRIsVALUE " not allowed in JSON" , CLASS_OF (obj ));
1040
+ }
1029
1041
} else if (rb_respond_to (obj , i_to_json )) {
1030
1042
tmp = rb_funcall (obj , i_to_json , 1 , vstate_get (data ));
1031
1043
Check_Type (tmp , T_STRING );
@@ -1126,6 +1138,7 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1126
1138
objState -> space_before = origState -> space_before ;
1127
1139
objState -> object_nl = origState -> object_nl ;
1128
1140
objState -> array_nl = origState -> array_nl ;
1141
+ objState -> as_json = origState -> as_json ;
1129
1142
return obj ;
1130
1143
}
1131
1144
@@ -1277,6 +1290,28 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1277
1290
return Qnil ;
1278
1291
}
1279
1292
1293
+ /*
1294
+ * call-seq: as_json()
1295
+ *
1296
+ * This string is put at the end of a line that holds a JSON array.
1297
+ */
1298
+ static VALUE cState_as_json (VALUE self )
1299
+ {
1300
+ GET_STATE (self );
1301
+ return state -> as_json ;
1302
+ }
1303
+
1304
+ /*
1305
+ * call-seq: as_json=(as_json)
1306
+ *
1307
+ * This string is put at the end of a line that holds a JSON array.
1308
+ */
1309
+ static VALUE cState_as_json_set (VALUE self , VALUE as_json )
1310
+ {
1311
+ GET_STATE (self );
1312
+ RB_OBJ_WRITE (self , & state -> as_json , rb_convert_type (as_json , T_DATA , "Proc" , "to_proc" ));
1313
+ return Qnil ;
1314
+ }
1280
1315
1281
1316
/*
1282
1317
* call-seq: check_circular?
@@ -1498,6 +1533,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
1498
1533
else if (key == sym_script_safe ) { state -> script_safe = RTEST (val ); }
1499
1534
else if (key == sym_escape_slash ) { state -> script_safe = RTEST (val ); }
1500
1535
else if (key == sym_strict ) { state -> strict = RTEST (val ); }
1536
+ else if (key == sym_as_json ) { state -> as_json = rb_convert_type (val , T_DATA , "Proc" , "to_proc" ); }
1501
1537
return ST_CONTINUE ;
1502
1538
}
1503
1539
@@ -1589,6 +1625,8 @@ void Init_generator(void)
1589
1625
rb_define_method (cState , "object_nl=" , cState_object_nl_set , 1 );
1590
1626
rb_define_method (cState , "array_nl" , cState_array_nl , 0 );
1591
1627
rb_define_method (cState , "array_nl=" , cState_array_nl_set , 1 );
1628
+ rb_define_method (cState , "as_json" , cState_as_json , 0 );
1629
+ rb_define_method (cState , "as_json=" , cState_as_json_set , 1 );
1592
1630
rb_define_method (cState , "max_nesting" , cState_max_nesting , 0 );
1593
1631
rb_define_method (cState , "max_nesting=" , cState_max_nesting_set , 1 );
1594
1632
rb_define_method (cState , "script_safe" , cState_script_safe , 0 );
@@ -1610,6 +1648,7 @@ void Init_generator(void)
1610
1648
rb_define_method (cState , "buffer_initial_length" , cState_buffer_initial_length , 0 );
1611
1649
rb_define_method (cState , "buffer_initial_length=" , cState_buffer_initial_length_set , 1 );
1612
1650
rb_define_method (cState , "generate" , cState_generate , -1 );
1651
+ rb_define_alias (cState , "generate_new" , "generate" ); // :nodoc:
1613
1652
1614
1653
rb_define_singleton_method (cState , "generate" , cState_m_generate , 3 );
1615
1654
@@ -1680,6 +1719,7 @@ void Init_generator(void)
1680
1719
sym_script_safe = ID2SYM (rb_intern ("script_safe" ));
1681
1720
sym_escape_slash = ID2SYM (rb_intern ("escape_slash" ));
1682
1721
sym_strict = ID2SYM (rb_intern ("strict" ));
1722
+ sym_as_json = ID2SYM (rb_intern ("as_json" ));
1683
1723
1684
1724
usascii_encindex = rb_usascii_encindex ();
1685
1725
utf8_encindex = rb_utf8_encindex ();
0 commit comments