json 3.0.2 → 3.1.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/CHANGES.md +9 -0
- data/ext/json/ext/fbuffer/fbuffer.h +4 -0
- data/ext/json/ext/generator/generator.c +156 -44
- data/ext/json/ext/json.h +6 -0
- data/ext/json/ext/parser/parser.c +59 -54
- data/lib/json/common.rb +16 -16
- data/lib/json/ext/generator/state.rb +2 -6
- data/lib/json/ext.rb +129 -3
- data/lib/json/truffle_ruby/generator.rb +110 -30
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2c5d1d2dfae6ea305b69988b2f277305a0b52f02a7a047c2a5d0602a54546f8
|
|
4
|
+
data.tar.gz: 3840fd11930f94e94b1ddbe6fede6831662192b93c0e1e5bf8296c858e93cf4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26e58633051da64fee887463df8df3b11ec934557726e9affbd96c04115f393ca05e164e9b1bfbcaa73ba7431ce0951d48b1f6214ad05b9ef13ab98e160b9f65
|
|
7
|
+
data.tar.gz: 6b83a6ff45819906f284a4851cad7b33c214dcc2794d74aa5a8a27ef80b8ed0c34ca853957a444ef1188a92480a2eaa92ca188dcedef4cbf37c1ea271ea0d551
|
data/CHANGES.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-10-13 (3.1.0)
|
|
6
|
+
|
|
7
|
+
* Added `rfc8785` generator option to canonicalize the output. Replaces the `json-canonicalization` with numerous correctness fixes.
|
|
8
|
+
* Use the `rb_len_t` type introduced in Ruby 4.1 to allow for proper 64bit support on LP64 platforms (Windows).
|
|
9
|
+
* JRuby: parser errors now include the position (`line`, `column` and the message suffix) as well as `json_path`, matching the C extension.
|
|
10
|
+
* Improved the accuracy of parser error's `line`, `column` and snipets in presence of multibyte characters.
|
|
11
|
+
* Fix `JSON.load` to work correctly when provided a `Zlib::GzipReader` as IO source.
|
|
12
|
+
* Reject non-ASCII BINARY strings during JSON generation. This was deprecated since a long time and scheduled to be removed for 3.0.
|
|
13
|
+
|
|
5
14
|
### 2026-09-09 (3.0.2)
|
|
6
15
|
|
|
7
16
|
* Fix `JSON.load_file` and `JSON.load_file!` to load on Ruby 2.7.0 through 2.7.2, which cannot parse a leading parameter before `...`.
|
|
@@ -169,6 +169,10 @@ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
|
169
169
|
|
|
170
170
|
static void fbuffer_append_str(FBuffer *fb, VALUE str)
|
|
171
171
|
{
|
|
172
|
+
if (RB_UNLIKELY(fb->io)) {
|
|
173
|
+
// Growing the buffer may flush it and invoke arbitrary Ruby code.
|
|
174
|
+
str = rb_str_new_frozen(str);
|
|
175
|
+
}
|
|
172
176
|
const char *ptr;
|
|
173
177
|
size_t len;
|
|
174
178
|
RSTRING_GETMEM(str, ptr, len);
|
|
@@ -27,14 +27,16 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
27
27
|
bool ascii_only;
|
|
28
28
|
bool script_safe;
|
|
29
29
|
bool strict;
|
|
30
|
+
bool rfc8785;
|
|
30
31
|
VALUE sort_keys;
|
|
31
32
|
} JSON_Generator_State;
|
|
32
33
|
|
|
33
|
-
static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8, default_sort_keys_proc
|
|
34
|
+
static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8, default_sort_keys_proc,
|
|
35
|
+
rfc8785_number_formatter_proc, rfc8785_sort_keys_proc;
|
|
34
36
|
|
|
35
37
|
static ID i_to_s, i_to_json, i_new, i_encode;
|
|
36
38
|
static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
|
|
37
|
-
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_strict, sym_as_json, sym_sort_keys;
|
|
39
|
+
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_strict, sym_as_json, sym_sort_keys, sym_rfc8785;
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
#define GET_STATE_TO(self, state) \
|
|
@@ -73,7 +75,7 @@ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *dat
|
|
|
73
75
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
74
76
|
static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
|
|
75
77
|
|
|
76
|
-
static int usascii_encindex, utf8_encindex
|
|
78
|
+
static int usascii_encindex, utf8_encindex;
|
|
77
79
|
|
|
78
80
|
NORETURN(static void) raise_generator_error_str(VALUE invalid_object, VALUE str)
|
|
79
81
|
{
|
|
@@ -768,6 +770,12 @@ static void vstate_spill(struct generate_json_data *data)
|
|
|
768
770
|
RB_OBJ_WRITTEN(vstate, Qundef, state->sort_keys);
|
|
769
771
|
}
|
|
770
772
|
|
|
773
|
+
static inline VALUE json_to_s(VALUE obj)
|
|
774
|
+
{
|
|
775
|
+
VALUE tmp = rb_funcall(obj, i_to_s, 0);
|
|
776
|
+
return StringValue(tmp);
|
|
777
|
+
}
|
|
778
|
+
|
|
771
779
|
static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
|
|
772
780
|
{
|
|
773
781
|
if (RB_UNLIKELY(!data->vstate)) {
|
|
@@ -863,21 +871,12 @@ NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data,
|
|
|
863
871
|
}
|
|
864
872
|
}
|
|
865
873
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
return utf8_string;
|
|
871
|
-
case ENC_CODERANGE_VALID:
|
|
872
|
-
// For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
|
|
873
|
-
// TODO: Raise in 3.0.0
|
|
874
|
-
rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
|
|
875
|
-
return utf8_string;
|
|
876
|
-
break;
|
|
877
|
-
}
|
|
874
|
+
str = rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
|
|
875
|
+
Check_Type(str, T_STRING);
|
|
876
|
+
if (!valid_json_string_p(str)) {
|
|
877
|
+
raise_generator_error(str, "source sequence is illegal/malformed utf-8");
|
|
878
878
|
}
|
|
879
|
-
|
|
880
|
-
return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
|
|
879
|
+
return str;
|
|
881
880
|
}
|
|
882
881
|
|
|
883
882
|
ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
@@ -892,12 +891,17 @@ ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *dat
|
|
|
892
891
|
|
|
893
892
|
static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
894
893
|
{
|
|
894
|
+
VALUE str = obj;
|
|
895
|
+
if (RB_UNLIKELY(buffer->io)) {
|
|
896
|
+
// IO writes can mutate the original string while we are reading it.
|
|
897
|
+
str = rb_str_new_frozen(str);
|
|
898
|
+
}
|
|
895
899
|
fbuffer_append_char(buffer, '"');
|
|
896
900
|
|
|
897
|
-
|
|
901
|
+
rb_len_t len;
|
|
898
902
|
search_state search;
|
|
899
903
|
search.buffer = buffer;
|
|
900
|
-
RSTRING_GETMEM(
|
|
904
|
+
RSTRING_GETMEM(str, search.ptr, len);
|
|
901
905
|
search.cursor = search.ptr;
|
|
902
906
|
search.end = search.ptr + len;
|
|
903
907
|
|
|
@@ -908,7 +912,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
908
912
|
search.chunk_end = NULL;
|
|
909
913
|
#endif /* HAVE_SIMD */
|
|
910
914
|
|
|
911
|
-
switch (json_str_coderange(
|
|
915
|
+
switch (json_str_coderange(str)) {
|
|
912
916
|
case ENC_CODERANGE_7BIT:
|
|
913
917
|
case ENC_CODERANGE_VALID:
|
|
914
918
|
if (RB_UNLIKELY(data->state->ascii_only)) {
|
|
@@ -924,6 +928,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
924
928
|
break;
|
|
925
929
|
}
|
|
926
930
|
fbuffer_append_char(buffer, '"');
|
|
931
|
+
RB_GC_GUARD(str);
|
|
927
932
|
}
|
|
928
933
|
|
|
929
934
|
static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
@@ -1037,16 +1042,19 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1037
1042
|
static inline long increase_depth(struct generate_json_data *data)
|
|
1038
1043
|
{
|
|
1039
1044
|
JSON_Generator_State *state = data->state;
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --data->depth);
|
|
1045
|
+
if (RB_UNLIKELY(data->depth >= state->max_nesting && state->max_nesting)) {
|
|
1046
|
+
rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", data->depth + 1);
|
|
1043
1047
|
}
|
|
1044
|
-
return depth;
|
|
1048
|
+
return ++data->depth;
|
|
1045
1049
|
}
|
|
1046
1050
|
|
|
1047
1051
|
static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1048
1052
|
{
|
|
1049
|
-
if (RB_UNLIKELY(data->state->
|
|
1053
|
+
if (RB_UNLIKELY(data->state->rfc8785)) {
|
|
1054
|
+
VALUE args[2] = {obj, data->state->strict ? data->state->as_json : Qnil};
|
|
1055
|
+
obj = rb_proc_call_with_block(rfc8785_sort_keys_proc, 2, args, Qnil);
|
|
1056
|
+
Check_Type(obj, T_HASH);
|
|
1057
|
+
} else if (RB_UNLIKELY(data->state->sort_keys)) {
|
|
1050
1058
|
obj = rb_proc_call_with_block(data->state->sort_keys, 1, &obj, Qnil);
|
|
1051
1059
|
Check_Type(obj, T_HASH);
|
|
1052
1060
|
}
|
|
@@ -1090,7 +1098,7 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
|
|
|
1090
1098
|
|
|
1091
1099
|
fbuffer_append_char(buffer, '[');
|
|
1092
1100
|
if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
|
|
1093
|
-
for (
|
|
1101
|
+
for (rb_len_t i = 0; i < RARRAY_LEN(obj); i++) {
|
|
1094
1102
|
if (i > 0) {
|
|
1095
1103
|
fbuffer_append_char(buffer, ',');
|
|
1096
1104
|
if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
|
|
@@ -1118,9 +1126,7 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
|
|
|
1118
1126
|
Check_Type(tmp, T_STRING);
|
|
1119
1127
|
fbuffer_append_str(buffer, tmp);
|
|
1120
1128
|
} else {
|
|
1121
|
-
|
|
1122
|
-
Check_Type(tmp, T_STRING);
|
|
1123
|
-
generate_json_string(buffer, data, tmp);
|
|
1129
|
+
generate_json_string(buffer, data, json_to_s(obj));
|
|
1124
1130
|
}
|
|
1125
1131
|
}
|
|
1126
1132
|
|
|
@@ -1139,15 +1145,29 @@ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data,
|
|
|
1139
1145
|
fbuffer_append(buffer, "true", 4);
|
|
1140
1146
|
}
|
|
1141
1147
|
|
|
1148
|
+
static void generate_json_rfc8785_number(FBuffer *buffer, VALUE obj)
|
|
1149
|
+
{
|
|
1150
|
+
VALUE str = rb_proc_call_with_block(rfc8785_number_formatter_proc, 1, &obj, Qnil);
|
|
1151
|
+
Check_Type(str, T_STRING);
|
|
1152
|
+
fbuffer_append_str(buffer, str);
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1142
1155
|
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1143
1156
|
{
|
|
1157
|
+
if (RB_UNLIKELY(data->state->rfc8785)) {
|
|
1158
|
+
generate_json_rfc8785_number(buffer, obj);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1144
1161
|
fbuffer_append_long(buffer, FIX2LONG(obj));
|
|
1145
1162
|
}
|
|
1146
1163
|
|
|
1147
1164
|
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1148
1165
|
{
|
|
1149
|
-
|
|
1150
|
-
|
|
1166
|
+
if (RB_UNLIKELY(data->state->rfc8785)) {
|
|
1167
|
+
generate_json_rfc8785_number(buffer, obj);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
fbuffer_append_str(buffer, json_to_s(obj));
|
|
1151
1171
|
}
|
|
1152
1172
|
|
|
1153
1173
|
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
@@ -1166,11 +1186,15 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
|
|
|
1166
1186
|
return;
|
|
1167
1187
|
}
|
|
1168
1188
|
}
|
|
1169
|
-
raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON",
|
|
1189
|
+
raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", json_to_s(obj));
|
|
1170
1190
|
}
|
|
1171
1191
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1192
|
+
fbuffer_append_str(buffer, json_to_s(obj));
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
if (RB_UNLIKELY(data->state->rfc8785)) {
|
|
1197
|
+
generate_json_rfc8785_number(buffer, obj);
|
|
1174
1198
|
return;
|
|
1175
1199
|
}
|
|
1176
1200
|
|
|
@@ -1291,10 +1315,28 @@ static void generate_json_no_fallback(FBuffer *buffer, struct generate_json_data
|
|
|
1291
1315
|
generate_json_general(buffer, data, obj, false);
|
|
1292
1316
|
}
|
|
1293
1317
|
|
|
1318
|
+
static void validate_rfc8785(JSON_Generator_State *state)
|
|
1319
|
+
{
|
|
1320
|
+
if (!state->rfc8785) return;
|
|
1321
|
+
|
|
1322
|
+
const char *option = state->indent ? "indent" :
|
|
1323
|
+
state->space ? "space" :
|
|
1324
|
+
state->space_before ? "space_before" :
|
|
1325
|
+
state->object_nl ? "object_nl" :
|
|
1326
|
+
state->array_nl ? "array_nl" :
|
|
1327
|
+
state->ascii_only ? "ascii_only" :
|
|
1328
|
+
state->script_safe ? "script_safe" :
|
|
1329
|
+
state->allow_nan ? "allow_nan" : NULL;
|
|
1330
|
+
if (option) {
|
|
1331
|
+
rb_raise(rb_eArgError, "%s cannot be used with rfc8785", option);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1294
1335
|
static VALUE generate_json_try(VALUE d)
|
|
1295
1336
|
{
|
|
1296
1337
|
struct generate_json_data *data = (struct generate_json_data *)d;
|
|
1297
1338
|
|
|
1339
|
+
validate_rfc8785(data->state);
|
|
1298
1340
|
data->func(data->buffer, data, data->obj);
|
|
1299
1341
|
|
|
1300
1342
|
return fbuffer_finalize(data->buffer);
|
|
@@ -1542,7 +1584,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
|
1542
1584
|
/*
|
|
1543
1585
|
* call-seq: as_json()
|
|
1544
1586
|
*
|
|
1545
|
-
*
|
|
1587
|
+
* Returns the callback used to convert unsupported objects in strict mode.
|
|
1546
1588
|
*/
|
|
1547
1589
|
static VALUE cState_as_json(VALUE self)
|
|
1548
1590
|
{
|
|
@@ -1550,16 +1592,28 @@ static VALUE cState_as_json(VALUE self)
|
|
|
1550
1592
|
return state->as_json;
|
|
1551
1593
|
}
|
|
1552
1594
|
|
|
1595
|
+
static VALUE as_json_config(VALUE value)
|
|
1596
|
+
{
|
|
1597
|
+
if (rb_obj_is_proc(value)) {
|
|
1598
|
+
return value;
|
|
1599
|
+
}
|
|
1600
|
+
VALUE proc = rb_check_funcall(value, rb_intern("to_proc"), 0, NULL);
|
|
1601
|
+
if (proc == Qundef || !rb_obj_is_proc(proc)) {
|
|
1602
|
+
rb_raise(rb_eTypeError, "as_json must be a Proc");
|
|
1603
|
+
}
|
|
1604
|
+
return proc;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1553
1607
|
/*
|
|
1554
1608
|
* call-seq: as_json=(as_json)
|
|
1555
1609
|
*
|
|
1556
|
-
*
|
|
1610
|
+
* Sets the Proc used to convert unsupported objects in strict mode.
|
|
1557
1611
|
*/
|
|
1558
1612
|
static VALUE cState_as_json_set(VALUE self, VALUE as_json)
|
|
1559
1613
|
{
|
|
1560
1614
|
rb_check_frozen(self);
|
|
1561
1615
|
GET_STATE(self);
|
|
1562
|
-
RB_OBJ_WRITE(self, &state->as_json,
|
|
1616
|
+
RB_OBJ_WRITE(self, &state->as_json, as_json_config(as_json));
|
|
1563
1617
|
return Qnil;
|
|
1564
1618
|
}
|
|
1565
1619
|
|
|
@@ -1733,9 +1787,34 @@ static VALUE cState_set_default_sort_keys_proc(VALUE self, VALUE proc)
|
|
|
1733
1787
|
if (!rb_obj_is_proc(proc)) {
|
|
1734
1788
|
rb_raise(rb_eTypeError, "sort_key_proc must be a Proc");
|
|
1735
1789
|
}
|
|
1790
|
+
if (default_sort_keys_proc) {
|
|
1791
|
+
rb_raise(rb_eArgError, "sort_key_proc can only be set once");
|
|
1792
|
+
}
|
|
1736
1793
|
return default_sort_keys_proc = proc;
|
|
1737
1794
|
}
|
|
1738
1795
|
|
|
1796
|
+
static VALUE cState_set_rfc8785_number_formatter_proc(VALUE self, VALUE proc)
|
|
1797
|
+
{
|
|
1798
|
+
if (!rb_obj_is_proc(proc)) {
|
|
1799
|
+
rb_raise(rb_eTypeError, "rfc8785_number_formatter_proc must be a Proc");
|
|
1800
|
+
}
|
|
1801
|
+
if (rfc8785_number_formatter_proc) {
|
|
1802
|
+
rb_raise(rb_eArgError, "rfc8785_number_formatter_proc can only be set once");
|
|
1803
|
+
}
|
|
1804
|
+
return rfc8785_number_formatter_proc = proc;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
static VALUE cState_set_rfc8785_sort_keys_proc(VALUE self, VALUE proc)
|
|
1808
|
+
{
|
|
1809
|
+
if (!rb_obj_is_proc(proc)) {
|
|
1810
|
+
rb_raise(rb_eTypeError, "rfc8785_sort_keys_proc must be a Proc");
|
|
1811
|
+
}
|
|
1812
|
+
if (rfc8785_sort_keys_proc) {
|
|
1813
|
+
rb_raise(rb_eArgError, "rfc8785_sort_keys_proc can only be set once");
|
|
1814
|
+
}
|
|
1815
|
+
return rfc8785_sort_keys_proc = proc;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1739
1818
|
static VALUE normalize_sort_keys(VALUE value)
|
|
1740
1819
|
{
|
|
1741
1820
|
if (rb_obj_is_proc(value)) {
|
|
@@ -1754,7 +1833,7 @@ static VALUE normalize_sort_keys(VALUE value)
|
|
|
1754
1833
|
*
|
|
1755
1834
|
* Get the value of sort_keys.
|
|
1756
1835
|
*/
|
|
1757
|
-
static VALUE
|
|
1836
|
+
static VALUE cState_sort_keys(VALUE self)
|
|
1758
1837
|
{
|
|
1759
1838
|
GET_STATE(self);
|
|
1760
1839
|
return state->sort_keys;
|
|
@@ -1774,7 +1853,33 @@ static VALUE cState_sort_keys_set(VALUE self, VALUE value)
|
|
|
1774
1853
|
rb_check_frozen(self);
|
|
1775
1854
|
GET_STATE(self);
|
|
1776
1855
|
RB_OBJ_WRITE(self, &state->sort_keys, normalize_sort_keys(value));
|
|
1777
|
-
return
|
|
1856
|
+
return state->sort_keys;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
/*
|
|
1861
|
+
* call-seq: rfc8785?
|
|
1862
|
+
*
|
|
1863
|
+
* Get whether RFC8785 (canonicalization) is enabled.
|
|
1864
|
+
*/
|
|
1865
|
+
static VALUE cState_rfc8785_p(VALUE self)
|
|
1866
|
+
{
|
|
1867
|
+
GET_STATE(self);
|
|
1868
|
+
return state->rfc8785 ? Qtrue : Qfalse;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
/*
|
|
1872
|
+
* call-seq: rfc8785=
|
|
1873
|
+
*
|
|
1874
|
+
* Sets whether RFC8785 (canonicalization) is enabled.
|
|
1875
|
+
*/
|
|
1876
|
+
|
|
1877
|
+
static VALUE cState_rfc8785_set(VALUE self, VALUE value)
|
|
1878
|
+
{
|
|
1879
|
+
rb_check_frozen(self);
|
|
1880
|
+
GET_STATE(self);
|
|
1881
|
+
state->rfc8785 = RTEST(value);
|
|
1882
|
+
return state->rfc8785 ? Qtrue : Qfalse;
|
|
1778
1883
|
}
|
|
1779
1884
|
|
|
1780
1885
|
static VALUE cState_allow_duplicate_key_p(VALUE self)
|
|
@@ -1797,8 +1902,7 @@ static VALUE cState_depth(VALUE self)
|
|
|
1797
1902
|
/*
|
|
1798
1903
|
* call-seq: depth=(depth)
|
|
1799
1904
|
*
|
|
1800
|
-
*
|
|
1801
|
-
* to the integer depth, max_nesting = 0 if no maximum should be checked.
|
|
1905
|
+
* Sets the current depth of data structure nesting to the integer +depth+.
|
|
1802
1906
|
*/
|
|
1803
1907
|
static VALUE cState_depth_set(VALUE self, VALUE depth)
|
|
1804
1908
|
{
|
|
@@ -1875,8 +1979,9 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1875
1979
|
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
|
|
1876
1980
|
else if (key == sym_strict) { state->strict = RTEST(val); }
|
|
1877
1981
|
else if (key == sym_allow_duplicate_key) { state->allow_duplicate_key = RTEST(val); }
|
|
1982
|
+
else if (key == sym_rfc8785) { state->rfc8785 = RTEST(val); }
|
|
1878
1983
|
else if (key == sym_as_json) {
|
|
1879
|
-
VALUE proc = RTEST(val) ?
|
|
1984
|
+
VALUE proc = RTEST(val) ? as_json_config(val) : Qfalse;
|
|
1880
1985
|
state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
|
|
1881
1986
|
state_write_value(data, &state->as_json, proc);
|
|
1882
1987
|
}
|
|
@@ -1911,6 +2016,7 @@ static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE con
|
|
|
1911
2016
|
rb_hash_foreach(config, configure_state_i, (VALUE)&data);
|
|
1912
2017
|
|
|
1913
2018
|
raise_argument_error_on_unknown_keywords(data.unknown_keywords);
|
|
2019
|
+
validate_rfc8785(state);
|
|
1914
2020
|
}
|
|
1915
2021
|
|
|
1916
2022
|
static VALUE cState_configure(VALUE self, VALUE opts)
|
|
@@ -1970,6 +2076,8 @@ void Init_generator(void)
|
|
|
1970
2076
|
VALUE mGenerator = rb_define_module_under(mExt, "Generator");
|
|
1971
2077
|
|
|
1972
2078
|
rb_global_variable(&default_sort_keys_proc);
|
|
2079
|
+
rb_global_variable(&rfc8785_number_formatter_proc);
|
|
2080
|
+
rb_global_variable(&rfc8785_sort_keys_proc);
|
|
1973
2081
|
|
|
1974
2082
|
rb_global_variable(&eGeneratorError);
|
|
1975
2083
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
|
@@ -1981,6 +2089,8 @@ void Init_generator(void)
|
|
|
1981
2089
|
rb_define_alloc_func(cState, cState_s_allocate);
|
|
1982
2090
|
rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
|
|
1983
2091
|
rb_define_singleton_method(cState, "default_sort_keys_proc=", cState_set_default_sort_keys_proc, 1);
|
|
2092
|
+
rb_define_singleton_method(cState, "rfc8785_number_formatter_proc=", cState_set_rfc8785_number_formatter_proc, 1);
|
|
2093
|
+
rb_define_singleton_method(cState, "rfc8785_sort_keys_proc=", cState_set_rfc8785_sort_keys_proc, 1);
|
|
1984
2094
|
|
|
1985
2095
|
rb_define_method(cState, "initialize", cState_initialize, -1);
|
|
1986
2096
|
rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
|
|
@@ -2018,8 +2128,10 @@ void Init_generator(void)
|
|
|
2018
2128
|
rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
|
|
2019
2129
|
rb_define_method(cState, "generate", cState_generate, -1);
|
|
2020
2130
|
rb_define_method(cState, "_generate_no_fallback", cState_generate_no_fallback, -1);
|
|
2021
|
-
rb_define_method(cState, "sort_keys",
|
|
2131
|
+
rb_define_method(cState, "sort_keys", cState_sort_keys, 0);
|
|
2022
2132
|
rb_define_method(cState, "sort_keys=", cState_sort_keys_set, 1);
|
|
2133
|
+
rb_define_method(cState, "rfc8785?", cState_rfc8785_p, 0);
|
|
2134
|
+
rb_define_method(cState, "rfc8785=", cState_rfc8785_set, 1);
|
|
2023
2135
|
|
|
2024
2136
|
rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
|
|
2025
2137
|
|
|
@@ -2049,10 +2161,10 @@ void Init_generator(void)
|
|
|
2049
2161
|
sym_as_json = ID2SYM(rb_intern("as_json"));
|
|
2050
2162
|
sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
|
|
2051
2163
|
sym_sort_keys = ID2SYM(rb_intern("sort_keys"));
|
|
2164
|
+
sym_rfc8785 = ID2SYM(rb_intern("rfc8785"));
|
|
2052
2165
|
|
|
2053
2166
|
usascii_encindex = rb_usascii_encindex();
|
|
2054
2167
|
utf8_encindex = rb_utf8_encindex();
|
|
2055
|
-
binary_encindex = rb_ascii8bit_encindex();
|
|
2056
2168
|
|
|
2057
2169
|
rb_require("json/ext/generator/state");
|
|
2058
2170
|
|
data/ext/json/ext/json.h
CHANGED