json 2.21.2 → 3.0.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/CHANGES.md +51 -1
- data/README.md +4 -84
- data/ext/json/ext/generator/generator.c +32 -38
- data/ext/json/ext/json.h +13 -0
- data/ext/json/ext/parser/parser.c +80 -84
- data/lib/json/common.rb +139 -398
- data/lib/json/ext/generator/state.rb +0 -27
- data/lib/json/ext.rb +0 -2
- data/lib/json/truffle_ruby/generator.rb +38 -80
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +13 -265
- metadata +1 -17
- data/lib/json/add/bigdecimal.rb +0 -58
- data/lib/json/add/complex.rb +0 -51
- data/lib/json/add/core.rb +0 -13
- data/lib/json/add/date.rb +0 -54
- data/lib/json/add/date_time.rb +0 -67
- data/lib/json/add/exception.rb +0 -49
- data/lib/json/add/ostruct.rb +0 -54
- data/lib/json/add/range.rb +0 -54
- data/lib/json/add/rational.rb +0 -49
- data/lib/json/add/regexp.rb +0 -48
- data/lib/json/add/set.rb +0 -48
- data/lib/json/add/string.rb +0 -35
- data/lib/json/add/struct.rb +0 -52
- data/lib/json/add/symbol.rb +0 -52
- data/lib/json/add/time.rb +0 -52
- data/lib/json/generic_object.rb +0 -67
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4963523aa43ad467929b9530b04f5c27a37dbbb1891186251d1495f3fac1f5ee
|
|
4
|
+
data.tar.gz: caf3f18bf24b587b0832f911b692f1e1149c1bfc5d14b5c5e1b255f6f95689f9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78c8ac1a917008d3724b2a2e708d96c929de3924e4d7e1d85eb87e02a0e0a0c827bbe320464b8bb2ab8f6816ba0e5d48a8d57d3d5f00b15093aad8b9f12ce66b
|
|
7
|
+
data.tar.gz: '03867f4f7fef6bd2c14e5bfc1e426b710ad662807306c3475b63a6464e20ed10cb59646b1d6ff2b8b9b88ecb74150d7619133d8e0993c1b9666c7a7e6dd9315b'
|
data/CHANGES.md
CHANGED
|
@@ -2,9 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-09-08 (3.0.1)
|
|
6
|
+
|
|
7
|
+
* Restore the `limit` positional argument of `JSON.dump`.
|
|
8
|
+
|
|
9
|
+
### 2026-09-07 (3.0.0)
|
|
10
|
+
|
|
11
|
+
* Add `JSON::ParserError#json_path` to locate parse errors in the document as a JSONPath-style string (e.g. `$.foo[0].bar`). For duplicate key errors it points at the duplicated key itself.
|
|
12
|
+
* Fix the parser to also reject lone trailing UTF-16 surrogates (`\uDCxx` with no leading partner), symmetric to the leading-surrogate case. The Java parser already rejected these; this closes the CRuby/JRuby parity gap.
|
|
13
|
+
|
|
14
|
+
### 2026-08-11 (3.0.0.rc1)
|
|
15
|
+
|
|
16
|
+
With the removal of the insecure `create_additions` option, `JSON.load` and `JSON.dump` are
|
|
17
|
+
now safe to use. Them being unsafe by default caused multiple security vulnerabilites in the past.
|
|
18
|
+
|
|
19
|
+
If you did depend on `create_additions`, the recommended migration is to [implement a custom serializer using
|
|
20
|
+
`JSON::Coder`](https://byroot.github.io/ruby/json/2025/08/02/whats-wrong-with-the-json-gem-api.html#the-create_additions-option).
|
|
21
|
+
|
|
22
|
+
All the mutable default options, such as `JSON.load_default_options` have been removed.
|
|
23
|
+
They were preventing Ractor compatiblity, and causing bug in libraries using JSON expecting the default behavior.
|
|
24
|
+
`JSON` methods now always behave the same unless monkey patched.
|
|
25
|
+
|
|
26
|
+
All methods options are now either keyword arguments or checked like keyword arguments, meaning
|
|
27
|
+
unknown options such as typos raise `ArgumentError`.
|
|
28
|
+
|
|
29
|
+
Duplicated keys are now rejected by default.
|
|
30
|
+
|
|
31
|
+
JavaScript comments in documents are no longer supported by default.
|
|
32
|
+
|
|
33
|
+
Numerous rarely used aliases have been removed.
|
|
34
|
+
|
|
35
|
+
* `JSON.load` defaults are now safe to use.
|
|
36
|
+
* All unknown options will now cause an `ArgumentError` rather than to be ignored.
|
|
37
|
+
* The `allow_comments` parsing option now defaults to `false`.
|
|
38
|
+
* The `allow_duplicate_key` option now defaults to `false`, for both parsing and generating JSON.
|
|
39
|
+
* Removed the `limit` positional argument of `JSON.dump`.
|
|
40
|
+
* Removed the `escape_slash` alias of `script_safe`.
|
|
41
|
+
* Removed `Kernel#j` and `Kernel#jj`.
|
|
42
|
+
* Removed `JSON.load_default_options`.
|
|
43
|
+
* Removed `JSON.unsafe_load_default_options`.
|
|
44
|
+
* Removed `JSON.dump_default_options`.
|
|
45
|
+
* Removed `JSON::State#[]` and `JSON::State#[]=`.
|
|
46
|
+
* Removed `JSON.unparse`.
|
|
47
|
+
* Removed `JSON.fast_generate`.
|
|
48
|
+
* Removed `JSON.fast_unparse`.
|
|
49
|
+
* Removed `JSON.pretty_unparse`.
|
|
50
|
+
* Removed `JSON.restore`.
|
|
51
|
+
* Removed `JSON::PRETTY_STATE_PROTOTYPE`.
|
|
52
|
+
* Removed the insecure `create_additions` option.
|
|
53
|
+
* Removed `JSON::GenericObject`.
|
|
54
|
+
|
|
5
55
|
### 2026-07-31 (2.21.2)
|
|
6
56
|
|
|
7
|
-
* Fix a use-after-free bug in `JSON::ResumableParser`. [GHSA-9hj4-r449-hfvc].
|
|
57
|
+
* Fix a use-after-free bug in `JSON::ResumableParser`. [GHSA-9hj4-r449-hfvc][CVE-2026-71847].
|
|
8
58
|
|
|
9
59
|
### 2026-07-13 (2.21.1)
|
|
10
60
|
|
data/README.md
CHANGED
|
@@ -14,10 +14,7 @@ UTF-16 surrogate pairs in order to be able to generate the whole range of
|
|
|
14
14
|
unicode code points.
|
|
15
15
|
|
|
16
16
|
All strings, that are to be encoded as JSON strings, should be UTF-8 byte
|
|
17
|
-
sequences on the Ruby side.
|
|
18
|
-
encoded, please use the to\_json\_raw\_object method of String (which produces
|
|
19
|
-
an object, that contains a byte array) and decode the result on the receiving
|
|
20
|
-
endpoint.
|
|
17
|
+
sequences on the Ruby side.
|
|
21
18
|
|
|
22
19
|
## Installation
|
|
23
20
|
|
|
@@ -49,8 +46,7 @@ JSON.generate(data)
|
|
|
49
46
|
```
|
|
50
47
|
|
|
51
48
|
You can also use the `pretty_generate` method (which formats the output more
|
|
52
|
-
verbosely and nicely)
|
|
53
|
-
checks generate performs, e. g. nesting deepness checks).
|
|
49
|
+
verbosely and nicely).
|
|
54
50
|
|
|
55
51
|
## Casting non native types
|
|
56
52
|
|
|
@@ -143,84 +139,12 @@ posts_json.map! { |post_json| JSON::Fragment.new(post_json) }
|
|
|
143
139
|
JSON.generate({ posts: posts_json, count: posts_json.count })
|
|
144
140
|
```
|
|
145
141
|
|
|
146
|
-
##
|
|
147
|
-
|
|
148
|
-
> [!CAUTION]
|
|
149
|
-
> You should never use `JSON.unsafe_load` nor `JSON.parse(str, create_additions: true)` to parse untrusted user input,
|
|
150
|
-
> as it can lead to remote code execution vulnerabilities.
|
|
151
|
-
|
|
152
|
-
To create a JSON document from a ruby data structure, you can call
|
|
153
|
-
`JSON.generate` like that:
|
|
154
|
-
|
|
155
|
-
```ruby
|
|
156
|
-
json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
|
157
|
-
# => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
To get back a ruby data structure from a JSON document, you have to call
|
|
161
|
-
JSON.parse on it:
|
|
162
|
-
|
|
163
|
-
```ruby
|
|
164
|
-
JSON.parse json
|
|
165
|
-
# => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Note, that the range from the original data structure is a simple
|
|
169
|
-
string now. The reason for this is, that JSON doesn't support ranges
|
|
170
|
-
or arbitrary classes. In this case the json library falls back to call
|
|
171
|
-
`Object#to_json`, which is the same as `#to_s.to_json`.
|
|
172
|
-
|
|
173
|
-
It's possible to add JSON support serialization to arbitrary classes by
|
|
174
|
-
simply implementing a more specialized version of the `#to_json method`, that
|
|
175
|
-
should return a JSON object (a hash converted to JSON with `#to_json`) like
|
|
176
|
-
this (don't forget the `*a` for all the arguments):
|
|
177
|
-
|
|
178
|
-
```ruby
|
|
179
|
-
class Range
|
|
180
|
-
def to_json(*a)
|
|
181
|
-
{
|
|
182
|
-
'json_class' => self.class.name, # = 'Range'
|
|
183
|
-
'data' => [ first, last, exclude_end? ]
|
|
184
|
-
}.to_json(*a)
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
The hash key `json_class` is the class, that will be asked to deserialise the
|
|
190
|
-
JSON representation later. In this case it's `Range`, but any namespace of
|
|
191
|
-
the form `A::B` or `::A::B` will do. All other keys are arbitrary and can be
|
|
192
|
-
used to store the necessary data to configure the object to be deserialised.
|
|
193
|
-
|
|
194
|
-
If the key `json_class` is found in a JSON object, the JSON parser checks
|
|
195
|
-
if the given class responds to the `json_create` class method. If so, it is
|
|
196
|
-
called with the JSON object converted to a Ruby hash. So a range can
|
|
197
|
-
be deserialised by implementing `Range.json_create` like this:
|
|
198
|
-
|
|
199
|
-
```ruby
|
|
200
|
-
class Range
|
|
201
|
-
def self.json_create(o)
|
|
202
|
-
new(*o['data'])
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Now it possible to serialise/deserialise ranges as well:
|
|
208
|
-
|
|
209
|
-
```ruby
|
|
210
|
-
json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
|
211
|
-
# => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
|
|
212
|
-
JSON.parse json
|
|
213
|
-
# => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
|
214
|
-
json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
|
215
|
-
# => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
|
|
216
|
-
JSON.unsafe_load json
|
|
217
|
-
# => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
|
218
|
-
```
|
|
142
|
+
## Pretty Printing
|
|
219
143
|
|
|
220
144
|
`JSON.generate` always creates the shortest possible string representation of a
|
|
221
145
|
ruby data structure in one line. This is good for data storage or network
|
|
222
146
|
protocols, but not so good for humans to read. Fortunately there's also
|
|
223
|
-
`JSON.pretty_generate`
|
|
147
|
+
`JSON.pretty_generate` that creates a more readable
|
|
224
148
|
output:
|
|
225
149
|
|
|
226
150
|
```ruby
|
|
@@ -245,10 +169,6 @@ output:
|
|
|
245
169
|
]
|
|
246
170
|
```
|
|
247
171
|
|
|
248
|
-
There are also the methods `Kernel#j` for generate, and `Kernel#jj` for
|
|
249
|
-
`pretty_generate` output to the console, that work analogous to Core Ruby's `p` and
|
|
250
|
-
the `pp` library's `pp` methods.
|
|
251
|
-
|
|
252
172
|
## Security
|
|
253
173
|
|
|
254
174
|
When parsing or serializing untrusted input, parser and generator options should never be user controlled.
|
|
@@ -9,12 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
/* ruby api and some helpers */
|
|
11
11
|
|
|
12
|
-
enum duplicate_key_action {
|
|
13
|
-
JSON_DEPRECATED = 0,
|
|
14
|
-
JSON_IGNORE,
|
|
15
|
-
JSON_RAISE,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
12
|
typedef struct JSON_Generator_StateStruct {
|
|
19
13
|
VALUE indent;
|
|
20
14
|
VALUE space;
|
|
@@ -27,8 +21,7 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
27
21
|
long depth;
|
|
28
22
|
long buffer_initial_length;
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
bool allow_duplicate_key;
|
|
32
25
|
bool as_json_single_arg;
|
|
33
26
|
bool allow_nan;
|
|
34
27
|
bool ascii_only;
|
|
@@ -41,7 +34,7 @@ static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_
|
|
|
41
34
|
|
|
42
35
|
static ID i_to_s, i_to_json, i_new, i_encode;
|
|
43
36
|
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,
|
|
44
|
-
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe,
|
|
37
|
+
sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_strict, sym_as_json, sym_sort_keys;
|
|
45
38
|
|
|
46
39
|
|
|
47
40
|
#define GET_STATE_TO(self, state) \
|
|
@@ -956,9 +949,8 @@ json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
|
|
|
956
949
|
arg->mixed_keys_encountered = true;
|
|
957
950
|
|
|
958
951
|
JSON_Generator_State *state = arg->data->state;
|
|
959
|
-
if (state->
|
|
960
|
-
|
|
961
|
-
rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 2, arg->hash, do_raise);
|
|
952
|
+
if (!state->allow_duplicate_key) {
|
|
953
|
+
rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 1, arg->hash);
|
|
962
954
|
}
|
|
963
955
|
}
|
|
964
956
|
|
|
@@ -1132,15 +1124,6 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
|
|
|
1132
1124
|
}
|
|
1133
1125
|
}
|
|
1134
1126
|
|
|
1135
|
-
static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1136
|
-
{
|
|
1137
|
-
if (data->state->strict) {
|
|
1138
|
-
generate_json_string(buffer, data, rb_sym2str(obj));
|
|
1139
|
-
} else {
|
|
1140
|
-
generate_json_fallback(buffer, data, obj);
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
1127
|
static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
1145
1128
|
{
|
|
1146
1129
|
fbuffer_append(buffer, "null", 4);
|
|
@@ -1226,7 +1209,13 @@ start:
|
|
|
1226
1209
|
} else if (RB_FLONUM_P(obj)) {
|
|
1227
1210
|
generate_json_float(buffer, data, obj);
|
|
1228
1211
|
} else if (RB_STATIC_SYM_P(obj)) {
|
|
1229
|
-
|
|
1212
|
+
if (data->state->strict) {
|
|
1213
|
+
obj = rb_sym2str(obj);
|
|
1214
|
+
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
|
|
1215
|
+
goto generate_string;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
generate_json_fallback(buffer, data, obj);
|
|
1230
1219
|
} else {
|
|
1231
1220
|
goto general;
|
|
1232
1221
|
}
|
|
@@ -1247,6 +1236,7 @@ start:
|
|
|
1247
1236
|
case T_STRING:
|
|
1248
1237
|
if (fallback && klass != rb_cString) goto general;
|
|
1249
1238
|
|
|
1239
|
+
generate_string:
|
|
1250
1240
|
if (RB_LIKELY(valid_json_string_p(obj))) {
|
|
1251
1241
|
raw_generate_json_string(buffer, data, obj);
|
|
1252
1242
|
} else if (as_json_called) {
|
|
@@ -1258,7 +1248,13 @@ start:
|
|
|
1258
1248
|
}
|
|
1259
1249
|
break;
|
|
1260
1250
|
case T_SYMBOL:
|
|
1261
|
-
|
|
1251
|
+
if (data->state->strict) {
|
|
1252
|
+
obj = rb_sym2str(obj);
|
|
1253
|
+
JSON_ASSERT(RBASIC_CLASS(obj) == rb_cString);
|
|
1254
|
+
goto generate_string;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
generate_json_fallback(buffer, data, obj);
|
|
1262
1258
|
break;
|
|
1263
1259
|
case T_FLOAT:
|
|
1264
1260
|
if (fallback && klass != rb_cFloat) goto general;
|
|
@@ -1784,14 +1780,7 @@ static VALUE cState_sort_keys_set(VALUE self, VALUE value)
|
|
|
1784
1780
|
static VALUE cState_allow_duplicate_key_p(VALUE self)
|
|
1785
1781
|
{
|
|
1786
1782
|
GET_STATE(self);
|
|
1787
|
-
|
|
1788
|
-
case JSON_IGNORE:
|
|
1789
|
-
return Qtrue;
|
|
1790
|
-
case JSON_DEPRECATED:
|
|
1791
|
-
return Qnil;
|
|
1792
|
-
default:
|
|
1793
|
-
return Qfalse;
|
|
1794
|
-
}
|
|
1783
|
+
return state->allow_duplicate_key ? Qtrue : Qfalse;
|
|
1795
1784
|
}
|
|
1796
1785
|
|
|
1797
1786
|
/*
|
|
@@ -1856,6 +1845,7 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
|
1856
1845
|
struct configure_state_data {
|
|
1857
1846
|
JSON_Generator_State *state;
|
|
1858
1847
|
VALUE vstate; // Ruby object that owns the state, or Qfalse if stack-allocated
|
|
1848
|
+
VALUE unknown_keywords;
|
|
1859
1849
|
};
|
|
1860
1850
|
|
|
1861
1851
|
static inline void state_write_value(struct configure_state_data *data, VALUE *field, VALUE value)
|
|
@@ -1883,9 +1873,8 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1883
1873
|
else if (key == sym_depth) { state->depth = depth_config(val); }
|
|
1884
1874
|
else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
|
|
1885
1875
|
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
|
|
1886
|
-
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
|
|
1887
1876
|
else if (key == sym_strict) { state->strict = RTEST(val); }
|
|
1888
|
-
else if (key == sym_allow_duplicate_key) { state->
|
|
1877
|
+
else if (key == sym_allow_duplicate_key) { state->allow_duplicate_key = RTEST(val); }
|
|
1889
1878
|
else if (key == sym_as_json) {
|
|
1890
1879
|
VALUE proc = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse;
|
|
1891
1880
|
state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
|
|
@@ -1894,6 +1883,12 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
|
|
|
1894
1883
|
else if (key == sym_sort_keys) {
|
|
1895
1884
|
state_write_value(data, &state->sort_keys, normalize_sort_keys(val));
|
|
1896
1885
|
}
|
|
1886
|
+
else {
|
|
1887
|
+
if (!data->unknown_keywords) {
|
|
1888
|
+
data->unknown_keywords = rb_obj_hide(rb_ary_new());
|
|
1889
|
+
}
|
|
1890
|
+
rb_ary_push(data->unknown_keywords, key);
|
|
1891
|
+
}
|
|
1897
1892
|
return ST_CONTINUE;
|
|
1898
1893
|
}
|
|
1899
1894
|
|
|
@@ -1907,12 +1902,15 @@ static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE con
|
|
|
1907
1902
|
|
|
1908
1903
|
struct configure_state_data data = {
|
|
1909
1904
|
.state = state,
|
|
1910
|
-
.vstate = vstate
|
|
1905
|
+
.vstate = vstate,
|
|
1906
|
+
.unknown_keywords = Qfalse,
|
|
1911
1907
|
};
|
|
1912
1908
|
|
|
1913
1909
|
// We assume in most cases few keys are set so it's faster to go over
|
|
1914
1910
|
// the provided keys than to check all possible keys.
|
|
1915
1911
|
rb_hash_foreach(config, configure_state_i, (VALUE)&data);
|
|
1912
|
+
|
|
1913
|
+
raise_argument_error_on_unknown_keywords(data.unknown_keywords);
|
|
1916
1914
|
}
|
|
1917
1915
|
|
|
1918
1916
|
static VALUE cState_configure(VALUE self, VALUE opts)
|
|
@@ -2006,9 +2004,6 @@ void Init_generator(void)
|
|
|
2006
2004
|
rb_define_method(cState, "script_safe", cState_script_safe, 0);
|
|
2007
2005
|
rb_define_method(cState, "script_safe?", cState_script_safe, 0);
|
|
2008
2006
|
rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
|
|
2009
|
-
rb_define_alias(cState, "escape_slash", "script_safe");
|
|
2010
|
-
rb_define_alias(cState, "escape_slash?", "script_safe?");
|
|
2011
|
-
rb_define_alias(cState, "escape_slash=", "script_safe=");
|
|
2012
2007
|
rb_define_method(cState, "strict", cState_strict, 0);
|
|
2013
2008
|
rb_define_method(cState, "strict?", cState_strict, 0);
|
|
2014
2009
|
rb_define_method(cState, "strict=", cState_strict_set, 1);
|
|
@@ -2050,7 +2045,6 @@ void Init_generator(void)
|
|
|
2050
2045
|
sym_depth = ID2SYM(rb_intern("depth"));
|
|
2051
2046
|
sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
|
|
2052
2047
|
sym_script_safe = ID2SYM(rb_intern("script_safe"));
|
|
2053
|
-
sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
|
|
2054
2048
|
sym_strict = ID2SYM(rb_intern("strict"));
|
|
2055
2049
|
sym_as_json = ID2SYM(rb_intern("as_json"));
|
|
2056
2050
|
sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
|
data/ext/json/ext/json.h
CHANGED
|
@@ -180,4 +180,17 @@ static inline VALUE json_rb_catch_obj(VALUE tag, VALUE (*func)(VALUE args), VALU
|
|
|
180
180
|
|
|
181
181
|
#endif // JSON_TRUFFLERUBY_RB_CATCH_BUG
|
|
182
182
|
|
|
183
|
+
static inline void raise_argument_error_on_unknown_keywords(VALUE unknown_keywords)
|
|
184
|
+
{
|
|
185
|
+
if (RB_UNLIKELY(unknown_keywords)) {
|
|
186
|
+
if (RARRAY_LEN(unknown_keywords) == 1) {
|
|
187
|
+
rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, RARRAY_AREF(unknown_keywords, 0));
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
VALUE keywords = rb_ary_join(unknown_keywords, rb_utf8_str_new_cstr(", "));
|
|
191
|
+
rb_raise(rb_eArgError, "unknown keywords: %" PRIsVALUE, keywords);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
183
196
|
#endif // _JSON_H_
|