diff --git a/CHANGES.md b/CHANGES.md
index b13642ae5..84fca3bb1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,22 @@
### Unreleased
+- The `allow_comments` parsing option now default to `false`.
+- The `allow_duplicate_key` option now defaults to `false`, for both parsing and generating JSON.
+- Removed `Kernel#j` and `Kernel#jj`.
+- Removed `JSON.load_default_options`.
+- Removed `JSON.unsafe_load_default_options`.
+- Removed `JSON.dump_default_options`.
+- Removed `JSON::State#[]` and `JSON::State#[]=`.
+- Removed `JSON.unparse`.
+- Removed `JSON.fast_generate`.
+- Removed `JSON.fast_unparse`.
+- Removed `JSON.pretty_unparse`.
+- Removed `JSON.restore`.
+- Removed `JSON::PRETTY_STATE_PROTOTYPE`.
+- Removed the insecure `create_additions` option.
+- Removed `JSON::GenericObject`.
+
### 2026-07-13 (2.21.1)
* Fix a compilation issue on Window and Microsoft Visual C++.
diff --git a/README.md b/README.md
index 5e6ffe48f..79a8c3f3e 100644
--- a/README.md
+++ b/README.md
@@ -143,79 +143,7 @@ posts_json.map! { |post_json| JSON::Fragment.new(post_json) }
JSON.generate({ posts: posts_json, count: posts_json.count })
```
-## Round-tripping arbitrary types
-
-> [!CAUTION]
-> You should never use `JSON.unsafe_load` nor `JSON.parse(str, create_additions: true)` to parse untrusted user input,
-> as it can lead to remote code execution vulnerabilities.
-
-To create a JSON document from a ruby data structure, you can call
-`JSON.generate` like that:
-
-```ruby
-json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
-# => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
-```
-
-To get back a ruby data structure from a JSON document, you have to call
-JSON.parse on it:
-
-```ruby
-JSON.parse json
-# => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
-```
-
-Note, that the range from the original data structure is a simple
-string now. The reason for this is, that JSON doesn't support ranges
-or arbitrary classes. In this case the json library falls back to call
-`Object#to_json`, which is the same as `#to_s.to_json`.
-
-It's possible to add JSON support serialization to arbitrary classes by
-simply implementing a more specialized version of the `#to_json method`, that
-should return a JSON object (a hash converted to JSON with `#to_json`) like
-this (don't forget the `*a` for all the arguments):
-
-```ruby
-class Range
- def to_json(*a)
- {
- 'json_class' => self.class.name, # = 'Range'
- 'data' => [ first, last, exclude_end? ]
- }.to_json(*a)
- end
-end
-```
-
-The hash key `json_class` is the class, that will be asked to deserialise the
-JSON representation later. In this case it's `Range`, but any namespace of
-the form `A::B` or `::A::B` will do. All other keys are arbitrary and can be
-used to store the necessary data to configure the object to be deserialised.
-
-If the key `json_class` is found in a JSON object, the JSON parser checks
-if the given class responds to the `json_create` class method. If so, it is
-called with the JSON object converted to a Ruby hash. So a range can
-be deserialised by implementing `Range.json_create` like this:
-
-```ruby
-class Range
- def self.json_create(o)
- new(*o['data'])
- end
-end
-```
-
-Now it possible to serialise/deserialise ranges as well:
-
-```ruby
-json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
-# => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
-JSON.parse json
-# => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
-json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
-# => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
-JSON.unsafe_load json
-# => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
-```
+## Pretty Printing
`JSON.generate` always creates the shortest possible string representation of a
ruby data structure in one line. This is good for data storage or network
diff --git a/benchmark/standalone.rb b/benchmark/standalone.rb
index deeb45dce..ebe759c5f 100644
--- a/benchmark/standalone.rb
+++ b/benchmark/standalone.rb
@@ -32,7 +32,7 @@
JSON.dump(obj)
end
else
- x.report('JSON.load(str)') do # max_nesting: false, allow_nan: true, allow_blank: true, create_additions: true
+ x.report('JSON.load(str)') do # max_nesting: false, allow_nan: true, allow_blank: true
JSON.load(str)
end
end
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 6f473325e..a45fd3928 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -9,12 +9,6 @@
/* ruby api and some helpers */
-enum duplicate_key_action {
- JSON_DEPRECATED = 0,
- JSON_IGNORE,
- JSON_RAISE,
-};
-
typedef struct JSON_Generator_StateStruct {
VALUE indent;
VALUE space;
@@ -27,8 +21,7 @@ typedef struct JSON_Generator_StateStruct {
long depth;
long buffer_initial_length;
- enum duplicate_key_action on_duplicate_key;
-
+ bool allow_duplicate_key;
bool as_json_single_arg;
bool allow_nan;
bool ascii_only;
@@ -956,9 +949,8 @@ json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
arg->mixed_keys_encountered = true;
JSON_Generator_State *state = arg->data->state;
- if (state->on_duplicate_key != JSON_IGNORE) {
- VALUE do_raise = state->on_duplicate_key == JSON_RAISE ? Qtrue : Qfalse;
- rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 2, arg->hash, do_raise);
+ if (!state->allow_duplicate_key) {
+ rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 1, arg->hash);
}
}
@@ -1784,14 +1776,7 @@ static VALUE cState_sort_keys_set(VALUE self, VALUE value)
static VALUE cState_allow_duplicate_key_p(VALUE self)
{
GET_STATE(self);
- switch (state->on_duplicate_key) {
- case JSON_IGNORE:
- return Qtrue;
- case JSON_DEPRECATED:
- return Qnil;
- default:
- return Qfalse;
- }
+ return state->allow_duplicate_key ? Qtrue : Qfalse;
}
/*
@@ -1885,7 +1870,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
else if (key == sym_strict) { state->strict = RTEST(val); }
- else if (key == sym_allow_duplicate_key) { state->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_allow_duplicate_key) { state->allow_duplicate_key = RTEST(val); }
else if (key == sym_as_json) {
VALUE proc = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse;
state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index d1c90ff8d..768931d34 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -403,19 +403,13 @@ typedef struct json_frame_stack_struct {
json_frame *ptr;
} json_frame_stack;
-enum deprecatable_action {
- JSON_DEPRECATED = 0,
- JSON_IGNORE,
- JSON_RAISE,
-};
-
typedef struct JSON_ParserStruct {
VALUE on_load_proc;
VALUE decimal_class;
ID decimal_method_id;
- enum deprecatable_action on_duplicate_key;
- enum deprecatable_action on_comment;
int max_nesting;
+ bool allow_comments;
+ bool allow_duplicate_key;
bool allow_nan;
bool allow_trailing_comma;
bool allow_control_characters;
@@ -435,7 +429,6 @@ typedef struct JSON_ParserStateStruct {
rvalue_cache name_cache;
int in_array;
int current_nesting;
- unsigned int emitted_deprecations;
VALUE parser;
} JSON_ParserState;
@@ -617,17 +610,6 @@ static void cursor_position(JSON_ParserState *state, long *line_out, long *colum
*column_out = column;
}
-static const unsigned int MAX_DEPRECATIONS = 5;
-
-static void emit_parse_warning(const char *message, JSON_ParserState *state)
-{
- long line, column;
- cursor_position(state, &line, &column);
-
- VALUE warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
- rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
-}
-
#define PARSE_ERROR_FRAGMENT_LEN 32
static VALUE build_parse_error_message(const char *format, JSON_ParserState *state)
@@ -766,11 +748,10 @@ static uint32_t unescape_unicode(JSON_ParserState *state, const char *sp, const
static const rb_data_type_t JSON_ParserConfig_type;
-const char *COMMENT_DEPRECATION_MESSAGE = "Encountered comment in JSON. This will raise an error in json 3.0 unless enabled via `allow_comments: true`";
NOINLINE(static) void
json_eat_comments(JSON_ParserState *state, JSON_ParserConfig *config, const char *resume_pos)
{
- if (config->on_comment == JSON_RAISE) {
+ if (!config->allow_comments) {
raise_syntax_error("unexpected token %s", state);
}
@@ -820,11 +801,6 @@ json_eat_comments(JSON_ParserState *state, JSON_ParserConfig *config, const char
raise_parse_error_at("unexpected token %s", state, eos(state) ? rewind_pos : start, eos(state));
break;
}
-
- if (config->on_comment == JSON_DEPRECATED && state->emitted_deprecations < MAX_DEPRECATIONS) {
- state->emitted_deprecations++;
- emit_parse_warning(COMMENT_DEPRECATION_MESSAGE, state);
- }
}
ALWAYS_INLINE(static) void
@@ -1193,17 +1169,6 @@ static VALUE json_find_duplicated_key(size_t count, const VALUE *pairs)
return Qfalse;
}
-NOINLINE(static) void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
-{
- VALUE message = rb_sprintf(
- "detected duplicate key %"PRIsVALUE" in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`",
- rb_inspect(duplicate_key)
- );
-
- emit_parse_warning(RSTRING_PTR(message), state);
- RB_GC_GUARD(message);
-}
-
NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
{
VALUE message = rb_sprintf(
@@ -1224,23 +1189,9 @@ NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE d
NOINLINE(static) void json_on_duplicate_key(JSON_ParserState *state, JSON_ParserConfig *config, size_t count, const VALUE *pairs)
{
- switch (config->on_duplicate_key) {
- case JSON_IGNORE:
- return;
-
- case JSON_DEPRECATED:
- // Only emit the first few deprecations to avoid spamming.
- if (state->emitted_deprecations < MAX_DEPRECATIONS) {
- state->emitted_deprecations++;
- emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
- }
- return;
-
- case JSON_RAISE:
- raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
- return;
+ if (!config->allow_duplicate_key) {
+ raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
}
- UNREACHABLE;
}
static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
@@ -2006,13 +1957,13 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
- else if (key == sym_allow_comments) { config->on_comment = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_allow_comments) { config->allow_comments = RTEST(val); }
else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); }
else if (key == sym_allow_invalid_escape) { config->allow_invalid_escape = RTEST(val); }
else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
else if (key == sym_freeze) { config->freeze = RTEST(val); }
else if (key == sym_on_load) { parser_config_wb_write(self, &config->on_load_proc, RTEST(val) ? val : Qfalse); }
- else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_allow_duplicate_key) { config->allow_duplicate_key = RTEST(val); }
else if (key == sym_decimal_class) {
if (RTEST(val)) {
if (rb_respond_to(val, i_try_convert)) {
@@ -2639,7 +2590,6 @@ static VALUE cResumableParser_clear(VALUE self)
parser->state.name_cache.length = 0;
parser->state.current_nesting = 0;
parser->state.in_array = 1;
- parser->state.emitted_deprecations = 0;
parser->state.start = parser->state.cursor = parser->state.end = NULL;
return self;
}
diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java
index f1617a051..ce1b5b57e 100644
--- a/java/src/json/ext/Generator.java
+++ b/java/src/json/ext/Generator.java
@@ -553,13 +553,8 @@ private void report(ThreadContext context, Session session) {
final GeneratorState state = session.getState(context);
if (!state.getAllowDuplicateKey()) {
- if (state.getDeprecateDuplicateKey()) {
- IRubyObject args[] = new IRubyObject[]{hash, context.getRuntime().getFalse()};
- info.jsonModule.get().callMethod(context, "on_mixed_keys_hash", args);
- } else {
- IRubyObject args[] = new IRubyObject[]{hash, context.getRuntime().getTrue()};
- info.jsonModule.get().callMethod(context, "on_mixed_keys_hash", args);
- }
+ IRubyObject args[] = new IRubyObject[]{hash};
+ info.jsonModule.get().callMethod(context, "on_mixed_keys_hash", args);
}
}
}
diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java
index 2d20ea461..1086bf6d3 100644
--- a/java/src/json/ext/GeneratorState.java
+++ b/java/src/json/ext/GeneratorState.java
@@ -35,7 +35,6 @@
*/
public class GeneratorState extends RubyObject {
private boolean allowDuplicateKey = false;
- private boolean deprecateDuplicateKey = true;
private static IRubyObject defaultSortKeyProc;
@@ -236,7 +235,6 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject vOrig) {
this.depth = orig.depth;
this.allowDuplicateKey = orig.allowDuplicateKey;
- this.deprecateDuplicateKey = orig.deprecateDuplicateKey;
this.sortKeys = orig.sortKeys;
return this;
@@ -272,30 +270,6 @@ public IRubyObject generate(ThreadContext context, IRubyObject obj) {
return generate(context, obj, context.nil);
}
- @JRubyMethod(name="[]")
- public IRubyObject op_aref(ThreadContext context, IRubyObject vName) {
- String name = vName.asJavaString();
- if (getMetaClass().isMethodBound(name, true)) {
- return send(context, vName, Block.NULL_BLOCK);
- } else {
- IRubyObject value = getInstanceVariables().getInstanceVariable("@" + name);
- return value == null ? context.nil : value;
- }
- }
-
- @JRubyMethod(name="[]=")
- public IRubyObject op_aset(ThreadContext context, IRubyObject vName, IRubyObject value) {
- checkFrozen();
- String name = vName.asJavaString();
- String nameWriter = name + "=";
- if (getMetaClass().isMethodBound(nameWriter, true)) {
- return send(context, context.runtime.newString(nameWriter), value, Block.NULL_BLOCK);
- } else {
- getInstanceVariables().setInstanceVariable("@" + name, value);
- }
- return context.nil;
- }
-
public ByteList getIndent() {
return indent;
}
@@ -550,8 +524,6 @@ private ByteList prepareByteList(ThreadContext context, IRubyObject value) {
public IRubyObject allow_duplicate_key_p(ThreadContext context) {
if (allowDuplicateKey) {
return context.runtime.getTrue();
- } else if (deprecateDuplicateKey) {
- return context.runtime.getNil();
}
return context.runtime.getFalse();
}
@@ -560,10 +532,6 @@ public boolean getAllowDuplicateKey() {
return allowDuplicateKey;
}
- public boolean getDeprecateDuplicateKey() {
- return deprecateDuplicateKey;
- }
-
/**
* State#configure(opts)
*
@@ -608,11 +576,7 @@ public IRubyObject _configure(ThreadContext context, IRubyObject vOpts) {
if (depth < 0) {
throw context.runtime.newArgumentError("depth must be >= 0 (got: " + depth + ")");
}
-
- if (opts.hasKey("allow_duplicate_key")) {
- this.allowDuplicateKey = opts.getBool("allow_duplicate_key", false);
- this.deprecateDuplicateKey = false;
- }
+ this.allowDuplicateKey = opts.getBool("allow_duplicate_key", false);
sortKeys = normalizeSortKeys(context, opts.get("sort_keys"));
@@ -645,15 +609,7 @@ public RubyHash to_h(ThreadContext context) {
result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
result.op_aset(context, runtime.newSymbol("buffer_initial_length"), buffer_initial_length_get(context));
result.op_aset(context, runtime.newSymbol("sort_keys"), sort_keys_get(context));
-
- if (this.allowDuplicateKey) {
- if (!this.deprecateDuplicateKey) {
- result.op_aset(context, runtime.newSymbol("allow_duplicate_key"), runtime.getTrue());
- }
- }
- else {
- result.op_aset(context, runtime.newSymbol("allow_duplicate_key"), runtime.getFalse());
- }
+ result.op_aset(context, runtime.newSymbol("allow_duplicate_key"), allow_duplicate_key_p(context));
for (String name: getInstanceVariableNameList()) {
result.op_aset(context, runtime.newSymbol(name.substring(1)), getInstanceVariables().getInstanceVariable(name));
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index c54d1a7f9..b2be38d15 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -46,11 +46,9 @@ public class Parser extends RubyObject {
private boolean allowNaN;
private boolean allowTrailingComma;
private boolean allowComments;
- private boolean deprecateComments;
private boolean allowControlCharacters;
private boolean allowInvalidEscape;
private boolean allowDuplicateKey;
- private boolean deprecateDuplicateKey;
private boolean symbolizeNames;
private boolean freeze;
private RubyProc onLoadProc;
@@ -97,25 +95,12 @@ public IRubyObject initialize(ThreadContext context, IRubyObject options) {
OptionsReader opts = new OptionsReader(context, options);
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
- if (opts.hasKey("allow_comments")) {
- this.allowComments = opts.getBool("allow_comments", false);
- this.deprecateComments = false;
- } else {
- this.allowComments = true;
- this.deprecateComments = true;
- }
-
+ this.allowComments = opts.getBool("allow_comments", false);
this.allowControlCharacters = opts.getBool("allow_control_characters", false);
this.allowInvalidEscape = opts.getBool("allow_invalid_escape", false);
this.allowTrailingComma = opts.getBool("allow_trailing_comma", false);
this.symbolizeNames = opts.getBool("symbolize_names", false);
- if (opts.hasKey("allow_duplicate_key")) {
- this.allowDuplicateKey = opts.getBool("allow_duplicate_key", false);
- this.deprecateDuplicateKey = false;
- } else {
- this.allowDuplicateKey = false;
- this.deprecateDuplicateKey = true;
- }
+ this.allowDuplicateKey = opts.getBool("allow_duplicate_key", false);
this.freeze = opts.getBool("freeze", false);
this.onLoadProc = opts.getProc("on_load");
@@ -585,16 +570,7 @@ private void onDuplicateKey(IRubyObject key) {
// match the C parser's message.
String keyInspect = key.callMethod(context, "to_s")
.callMethod(context, "inspect").asJavaString();
- if (config.deprecateDuplicateKey) {
- if (emittedDeprecations < MAX_DEPRECATIONS) {
- emittedDeprecations++;
- context.runtime.getWarnings().warning(
- "detected duplicate key " + keyInspect + " in JSON object. " +
- "This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`");
- }
- } else {
- throw newException(Utils.M_PARSER_ERROR, "duplicate key " + keyInspect);
- }
+ throw newException(Utils.M_PARSER_ERROR, "duplicate key " + keyInspect);
}
private int parseDigits(long value) {
@@ -859,15 +835,7 @@ private void eatWhitespace() {
private void eatComments() {
if (!config.allowComments) {
- if (config.deprecateComments) {
- if (emittedDeprecations < MAX_DEPRECATIONS) {
- emittedDeprecations++;
- context.runtime.getWarnings().warning(
- "Encountered comment in JSON. This will raise an error in json 3.0 unless enabled via `allow_comments: true`");
- }
- } else {
- throw unexpectedToken(cursor, end);
- }
+ throw unexpectedToken(cursor, end);
}
int start = cursor;
diff --git a/lib/json.rb b/lib/json.rb
index d1e94147d..9d6e969ca 100644
--- a/lib/json.rb
+++ b/lib/json.rb
@@ -139,18 +139,12 @@
# Option +allow_duplicate_key+ specifies whether duplicate keys in objects
# should be ignored or cause an error to be raised:
#
-# When not specified:
-# # The last value is used and a deprecation warning emitted.
-# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
-# # warning: detected duplicate keys in JSON object.
-# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
+# When set to +false+, the default:
+# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
#
# When set to +true+:
# # The last value is used.
-# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
-#
-# When set to +false+, the future default:
-# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
+# JSON.parse('{"a": 1, "a":2}', allow_duplicate_key: true) => {"a" => 2}
#
# ---
#
@@ -188,13 +182,11 @@
# JavaScript style comments (either // comment or /* comment */);
# defaults to +false+.
#
-# When not specified, a deprecation warning is emitted if a comment is encountered.
+# When set to +false+, the default:
+# JSON.parse('/* comment */ {"a": 1, "a":2}') # unexpected character: '/' at line 1 column 1 (JSON::ParserError)
#
# When set to +true+, comments are ignored:
-# JSON.parse('/* comment */ {"a": 1, "a":2}') # => {"a" => 2}
-#
-# When set to +false+, the future default:
-# JSON.parse('/* comment */ {"a": 1, "a":2}') # unexpected character: '/' at line 1 column 1 (JSON::ParserError)
+# JSON.parse('/* comment */ {"a": 1, "a":2} // more comment') # => {"a" => 2}
#
# ---
#
@@ -265,11 +257,6 @@
# ruby = JSON.parse(source, {array_class: Set})
# ruby # => #
#
-# ---
-#
-# Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
-# See {\JSON Additions}[#module-JSON-label-JSON+Additions].
-#
# === Generating \JSON
#
# To generate a Ruby \String containing \JSON data,
@@ -358,18 +345,13 @@
# hashes with duplicate keys should be allowed or produce an error.
# defaults to emit a deprecation warning.
#
-# With the default, (not set):
-# Warning[:deprecated] = true
+# With the default, false:
# JSON.generate({ foo: 1, "foo" => 2 })
-# # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
-# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
-# # => '{"foo":1,"foo":2}'
-#
-# With false
-# JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
# # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
#
-# In version 3.0, false will become the default.
+# With true
+# JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: true)
+# # => '{"foo":1,"foo":2}'
#
# ---
#
@@ -452,241 +434,6 @@
# }
# }
#
-# == \JSON Additions
-#
-# Note that JSON Additions must only be used with trusted data, and is
-# deprecated.
-#
-# When you "round trip" a non-\String object from Ruby to \JSON and back,
-# you have a new \String, instead of the object you began with:
-# ruby0 = Range.new(0, 2)
-# json = JSON.generate(ruby0)
-# json # => '0..2"'
-# ruby1 = JSON.parse(json)
-# ruby1 # => '0..2'
-# ruby1.class # => String
-#
-# You can use \JSON _additions_ to preserve the original object.
-# The addition is an extension of a ruby class, so that:
-# - \JSON.generate stores more information in the \JSON string.
-# - \JSON.parse, called with option +create_additions+,
-# uses that information to create a proper Ruby object.
-#
-# This example shows a \Range being generated into \JSON
-# and parsed back into Ruby, both without and with
-# the addition for \Range:
-# ruby = Range.new(0, 2)
-# # This passage does not use the addition for Range.
-# json0 = JSON.generate(ruby)
-# ruby0 = JSON.parse(json0)
-# # This passage uses the addition for Range.
-# require 'json/add/range'
-# json1 = JSON.generate(ruby)
-# ruby1 = JSON.parse(json1, create_additions: true)
-# # Make a nice display.
-# display = <<~EOT
-# Generated JSON:
-# Without addition: #{json0} (#{json0.class})
-# With addition: #{json1} (#{json1.class})
-# Parsed JSON:
-# Without addition: #{ruby0.inspect} (#{ruby0.class})
-# With addition: #{ruby1.inspect} (#{ruby1.class})
-# EOT
-# puts display
-#
-# This output shows the different results:
-# Generated JSON:
-# Without addition: "0..2" (String)
-# With addition: {"json_class":"Range","a":[0,2,false]} (String)
-# Parsed JSON:
-# Without addition: "0..2" (String)
-# With addition: 0..2 (Range)
-#
-# The \JSON module includes additions for certain classes.
-# You can also craft custom additions.
-# See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
-#
-# === Built-in Additions
-#
-# The \JSON module includes additions for certain classes.
-# To use an addition, +require+ its source:
-# - BigDecimal: require 'json/add/bigdecimal'
-# - Complex: require 'json/add/complex'
-# - Date: require 'json/add/date'
-# - DateTime: require 'json/add/date_time'
-# - Exception: require 'json/add/exception'
-# - OpenStruct: require 'json/add/ostruct'
-# - Range: require 'json/add/range'
-# - Rational: require 'json/add/rational'
-# - Regexp: require 'json/add/regexp'
-# - Set: require 'json/add/set'
-# - Struct: require 'json/add/struct'
-# - Symbol: require 'json/add/symbol'
-# - Time: require 'json/add/time'
-#
-# To reduce punctuation clutter, the examples below
-# show the generated \JSON via +puts+, rather than the usual +inspect+,
-#
-# \BigDecimal:
-# require 'json/add/bigdecimal'
-# ruby0 = BigDecimal(0) # 0.0
-# json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
-# ruby1 = JSON.parse(json, create_additions: true) # 0.0
-# ruby1.class # => BigDecimal
-#
-# \Complex:
-# require 'json/add/complex'
-# ruby0 = Complex(1+0i) # 1+0i
-# json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
-# ruby1 = JSON.parse(json, create_additions: true) # 1+0i
-# ruby1.class # Complex
-#
-# \Date:
-# require 'json/add/date'
-# ruby0 = Date.today # 2020-05-02
-# json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
-# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
-# ruby1.class # Date
-#
-# \DateTime:
-# require 'json/add/date_time'
-# ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
-# json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0}
-# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
-# ruby1.class # DateTime
-#
-# \Exception (and its subclasses including \RuntimeError):
-# require 'json/add/exception'
-# ruby0 = Exception.new('A message') # A message
-# json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
-# ruby1 = JSON.parse(json, create_additions: true) # A message
-# ruby1.class # Exception
-# ruby0 = RuntimeError.new('Another message') # Another message
-# json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
-# ruby1 = JSON.parse(json, create_additions: true) # Another message
-# ruby1.class # RuntimeError
-#
-# \OpenStruct:
-# require 'json/add/ostruct'
-# ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #
-# json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
-# ruby1 = JSON.parse(json, create_additions: true) # #
-# ruby1.class # OpenStruct
-#
-# \Range:
-# require 'json/add/range'
-# ruby0 = Range.new(0, 2) # 0..2
-# json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
-# ruby1 = JSON.parse(json, create_additions: true) # 0..2
-# ruby1.class # Range
-#
-# \Rational:
-# require 'json/add/rational'
-# ruby0 = Rational(1, 3) # 1/3
-# json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
-# ruby1 = JSON.parse(json, create_additions: true) # 1/3
-# ruby1.class # Rational
-#
-# \Regexp:
-# require 'json/add/regexp'
-# ruby0 = Regexp.new('foo') # (?-mix:foo)
-# json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
-# ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
-# ruby1.class # Regexp
-#
-# \Set:
-# require 'json/add/set'
-# ruby0 = Set.new([0, 1, 2]) # #
-# json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
-# ruby1 = JSON.parse(json, create_additions: true) # #
-# ruby1.class # Set
-#
-# \Struct:
-# require 'json/add/struct'
-# Customer = Struct.new(:name, :address) # Customer
-# ruby0 = Customer.new("Dave", "123 Main") # #
-# json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
-# ruby1 = JSON.parse(json, create_additions: true) # #
-# ruby1.class # Customer
-#
-# \Symbol:
-# require 'json/add/symbol'
-# ruby0 = :foo # foo
-# json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
-# ruby1 = JSON.parse(json, create_additions: true) # foo
-# ruby1.class # Symbol
-#
-# \Time:
-# require 'json/add/time'
-# ruby0 = Time.now # 2020-05-02 11:28:26 -0500
-# json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
-# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
-# ruby1.class # Time
-#
-#
-# === Custom \JSON Additions
-#
-# In addition to the \JSON additions provided,
-# you can craft \JSON additions of your own,
-# either for Ruby built-in classes or for user-defined classes.
-#
-# Here's a user-defined class +Foo+:
-# class Foo
-# attr_accessor :bar, :baz
-# def initialize(bar, baz)
-# self.bar = bar
-# self.baz = baz
-# end
-# end
-#
-# Here's the \JSON addition for it:
-# # Extend class Foo with JSON addition.
-# class Foo
-# # Serialize Foo object with its class name and arguments
-# def to_json(*args)
-# {
-# JSON.create_id => self.class.name,
-# 'a' => [ bar, baz ]
-# }.to_json(*args)
-# end
-# # Deserialize JSON string by constructing new Foo object with arguments.
-# def self.json_create(object)
-# new(*object['a'])
-# end
-# end
-#
-# Demonstration:
-# require 'json'
-# # This Foo object has no custom addition.
-# foo0 = Foo.new(0, 1)
-# json0 = JSON.generate(foo0)
-# obj0 = JSON.parse(json0)
-# # Lood the custom addition.
-# require_relative 'foo_addition'
-# # This foo has the custom addition.
-# foo1 = Foo.new(0, 1)
-# json1 = JSON.generate(foo1)
-# obj1 = JSON.parse(json1, create_additions: true)
-# # Make a nice display.
-# display = <<~EOT
-# Generated JSON:
-# Without custom addition: #{json0} (#{json0.class})
-# With custom addition: #{json1} (#{json1.class})
-# Parsed JSON:
-# Without custom addition: #{obj0.inspect} (#{obj0.class})
-# With custom addition: #{obj1.inspect} (#{obj1.class})
-# EOT
-# puts display
-#
-# Output:
-#
-# Generated JSON:
-# Without custom addition: "#" (String)
-# With custom addition: {"json_class":"Foo","a":[0,1]} (String)
-# Parsed JSON:
-# Without custom addition: "#" (String)
-# With custom addition: # (Foo)
-#
module JSON
require 'json/version'
require 'json/ext'
diff --git a/lib/json/add/bigdecimal.rb b/lib/json/add/bigdecimal.rb
deleted file mode 100644
index 5dbc12c07..000000000
--- a/lib/json/add/bigdecimal.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-begin
- require 'bigdecimal'
-rescue LoadError
-end
-
-class BigDecimal
-
- # See #as_json.
- def self.json_create(object)
- BigDecimal._load object['b']
- end
-
- # Methods BigDecimal#as_json and +BigDecimal.json_create+ may be used
- # to serialize and deserialize a \BigDecimal object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method BigDecimal#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/bigdecimal'
- # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
- # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
- # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object:
- #
- # BigDecimal.json_create(x) # => 0.2e1
- # BigDecimal.json_create(y) # => 0.2e1
- # BigDecimal.json_create(z) # => 0.2e1
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'b' => _dump.force_encoding(Encoding::UTF_8),
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/bigdecimal'
- # puts BigDecimal(2).to_json
- # puts BigDecimal(2.0, 4).to_json
- # puts BigDecimal(Complex(2, 0)).to_json
- #
- # Output:
- #
- # {"json_class":"BigDecimal","b":"27:0.2e1"}
- # {"json_class":"BigDecimal","b":"36:0.2e1"}
- # {"json_class":"BigDecimal","b":"27:0.2e1"}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end if defined?(::BigDecimal)
diff --git a/lib/json/add/complex.rb b/lib/json/add/complex.rb
deleted file mode 100644
index a69002eff..000000000
--- a/lib/json/add/complex.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Complex
-
- # See #as_json.
- def self.json_create(object)
- Complex(object['r'], object['i'])
- end
-
- # Methods Complex#as_json and +Complex.json_create+ may be used
- # to serialize and deserialize a \Complex object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Complex#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/complex'
- # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
- # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Complex object:
- #
- # Complex.json_create(x) # => (2+0i)
- # Complex.json_create(y) # => (2.0+4i)
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'r' => real,
- 'i' => imag,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/complex'
- # puts Complex(2).to_json
- # puts Complex(2.0, 4).to_json
- #
- # Output:
- #
- # {"json_class":"Complex","r":2,"i":0}
- # {"json_class":"Complex","r":2.0,"i":4}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/core.rb b/lib/json/add/core.rb
deleted file mode 100644
index 61ff45421..000000000
--- a/lib/json/add/core.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# This file requires the implementations of ruby core's custom objects for
-# serialisation/deserialisation.
-
-require 'json/add/date'
-require 'json/add/date_time'
-require 'json/add/exception'
-require 'json/add/range'
-require 'json/add/regexp'
-require 'json/add/string'
-require 'json/add/struct'
-require 'json/add/symbol'
-require 'json/add/time'
diff --git a/lib/json/add/date.rb b/lib/json/add/date.rb
deleted file mode 100644
index 66965d491..000000000
--- a/lib/json/add/date.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-require 'date'
-
-class Date
-
- # See #as_json.
- def self.json_create(object)
- civil(*object.values_at('y', 'm', 'd', 'sg'))
- end
-
- alias start sg unless method_defined?(:start)
-
- # Methods Date#as_json and +Date.json_create+ may be used
- # to serialize and deserialize a \Date object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Date#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/date'
- # x = Date.today.as_json
- # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Date object:
- #
- # Date.json_create(x)
- # # => #
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'y' => year,
- 'm' => month,
- 'd' => day,
- 'sg' => start,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/date'
- # puts Date.today.to_json
- #
- # Output:
- #
- # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/date_time.rb b/lib/json/add/date_time.rb
deleted file mode 100644
index 569f6ec17..000000000
--- a/lib/json/add/date_time.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-require 'date'
-
-class DateTime
-
- # See #as_json.
- def self.json_create(object)
- args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
- of_a, of_b = object['of'].split('/')
- if of_b and of_b != '0'
- args << Rational(of_a.to_i, of_b.to_i)
- else
- args << of_a
- end
- args << object['sg']
- civil(*args)
- end
-
- alias start sg unless method_defined?(:start)
-
- # Methods DateTime#as_json and +DateTime.json_create+ may be used
- # to serialize and deserialize a \DateTime object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method DateTime#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/datetime'
- # x = DateTime.now.as_json
- # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object:
- #
- # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'y' => year,
- 'm' => month,
- 'd' => day,
- 'H' => hour,
- 'M' => min,
- 'S' => sec,
- 'of' => offset.to_s,
- 'sg' => start,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/datetime'
- # puts DateTime.now.to_json
- #
- # Output:
- #
- # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
-
-
diff --git a/lib/json/add/exception.rb b/lib/json/add/exception.rb
deleted file mode 100644
index 5338ff83d..000000000
--- a/lib/json/add/exception.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Exception
-
- # See #as_json.
- def self.json_create(object)
- result = new(object['m'])
- result.set_backtrace object['b']
- result
- end
-
- # Methods Exception#as_json and +Exception.json_create+ may be used
- # to serialize and deserialize a \Exception object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Exception#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/exception'
- # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Exception object:
- #
- # Exception.json_create(x) # => #
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'm' => message,
- 'b' => backtrace,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/exception'
- # puts Exception.new('Foo').to_json
- #
- # Output:
- #
- # {"json_class":"Exception","m":"Foo","b":null}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/ostruct.rb b/lib/json/add/ostruct.rb
deleted file mode 100644
index 534403b78..000000000
--- a/lib/json/add/ostruct.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-begin
- require 'ostruct'
-rescue LoadError
-end
-
-class OpenStruct
-
- # See #as_json.
- def self.json_create(object)
- new(object['t'] || object[:t])
- end
-
- # Methods OpenStruct#as_json and +OpenStruct.json_create+ may be used
- # to serialize and deserialize a \OpenStruct object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method OpenStruct#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/ostruct'
- # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json
- # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object:
- #
- # OpenStruct.json_create(x)
- # # => #
- #
- def as_json(*)
- klass = self.class.name
- klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
- {
- JSON.create_id => klass,
- 't' => table,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/ostruct'
- # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json
- #
- # Output:
- #
- # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end if defined?(::OpenStruct)
diff --git a/lib/json/add/range.rb b/lib/json/add/range.rb
deleted file mode 100644
index eb4b29a8e..000000000
--- a/lib/json/add/range.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Range
-
- # See #as_json.
- def self.json_create(object)
- new(*object['a'])
- end
-
- # Methods Range#as_json and +Range.json_create+ may be used
- # to serialize and deserialize a \Range object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Range#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/range'
- # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
- # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
- # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Range object:
- #
- # Range.json_create(x) # => 1..4
- # Range.json_create(y) # => 1...4
- # Range.json_create(z) # => "a".."d"
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'a' => [ first, last, exclude_end? ]
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/range'
- # puts (1..4).to_json
- # puts (1...4).to_json
- # puts ('a'..'d').to_json
- #
- # Output:
- #
- # {"json_class":"Range","a":[1,4,false]}
- # {"json_class":"Range","a":[1,4,true]}
- # {"json_class":"Range","a":["a","d",false]}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/rational.rb b/lib/json/add/rational.rb
deleted file mode 100644
index 1eb231474..000000000
--- a/lib/json/add/rational.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Rational
-
- # See #as_json.
- def self.json_create(object)
- Rational(object['n'], object['d'])
- end
-
- # Methods Rational#as_json and +Rational.json_create+ may be used
- # to serialize and deserialize a \Rational object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Rational#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/rational'
- # x = Rational(2, 3).as_json
- # # => {"json_class"=>"Rational", "n"=>2, "d"=>3}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Rational object:
- #
- # Rational.json_create(x)
- # # => (2/3)
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'n' => numerator,
- 'd' => denominator,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/rational'
- # puts Rational(2, 3).to_json
- #
- # Output:
- #
- # {"json_class":"Rational","n":2,"d":3}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/regexp.rb b/lib/json/add/regexp.rb
deleted file mode 100644
index f033dd1de..000000000
--- a/lib/json/add/regexp.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Regexp
-
- # See #as_json.
- def self.json_create(object)
- new(object['s'], object['o'])
- end
-
- # Methods Regexp#as_json and +Regexp.json_create+ may be used
- # to serialize and deserialize a \Regexp object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Regexp#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/regexp'
- # x = /foo/.as_json
- # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object:
- #
- # Regexp.json_create(x) # => /foo/
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'o' => options,
- 's' => source,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/regexp'
- # puts /foo/.to_json
- #
- # Output:
- #
- # {"json_class":"Regexp","o":0,"s":"foo"}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/set.rb b/lib/json/add/set.rb
deleted file mode 100644
index c521d8b90..000000000
--- a/lib/json/add/set.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-defined?(::Set) or require 'set'
-
-class Set
-
- # See #as_json.
- def self.json_create(object)
- new object['a']
- end
-
- # Methods Set#as_json and +Set.json_create+ may be used
- # to serialize and deserialize a \Set object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Set#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/set'
- # x = Set.new(%w/foo bar baz/).as_json
- # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Set object:
- #
- # Set.json_create(x) # => #
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 'a' => to_a,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/set'
- # puts Set.new(%w/foo bar baz/).to_json
- #
- # Output:
- #
- # {"json_class":"Set","a":["foo","bar","baz"]}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
-
diff --git a/lib/json/add/string.rb b/lib/json/add/string.rb
deleted file mode 100644
index 9c3bde27f..000000000
--- a/lib/json/add/string.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class String
- # call-seq: json_create(o)
- #
- # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
- # key "raw"). The Ruby String can be created by this class method.
- def self.json_create(object)
- object["raw"].pack("C*")
- end
-
- # call-seq: to_json_raw_object()
- #
- # This method creates a raw object hash, that can be nested into
- # other data structures and will be generated as a raw string. This
- # method should be used, if you want to convert raw strings to JSON
- # instead of UTF-8 strings, e. g. binary data.
- def to_json_raw_object
- {
- JSON.create_id => self.class.name,
- "raw" => unpack("C*"),
- }
- end
-
- # call-seq: to_json_raw(*args)
- #
- # This method creates a JSON text from the result of a call to
- # to_json_raw_object of this String.
- def to_json_raw(...)
- to_json_raw_object.to_json(...)
- end
-end
diff --git a/lib/json/add/struct.rb b/lib/json/add/struct.rb
deleted file mode 100644
index 98c38d326..000000000
--- a/lib/json/add/struct.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Struct
-
- # See #as_json.
- def self.json_create(object)
- new(*object['v'])
- end
-
- # Methods Struct#as_json and +Struct.json_create+ may be used
- # to serialize and deserialize a \Struct object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Struct#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/struct'
- # Customer = Struct.new('Customer', :name, :address, :zip)
- # x = Struct::Customer.new.as_json
- # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Struct object:
- #
- # Struct::Customer.json_create(x)
- # # => #
- #
- def as_json(*)
- klass = self.class.name
- klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
- {
- JSON.create_id => klass,
- 'v' => values,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/struct'
- # Customer = Struct.new('Customer', :name, :address, :zip)
- # puts Struct::Customer.new.to_json
- #
- # Output:
- #
- # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/add/symbol.rb b/lib/json/add/symbol.rb
deleted file mode 100644
index 20dd59485..000000000
--- a/lib/json/add/symbol.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Symbol
-
- # Methods Symbol#as_json and +Symbol.json_create+ may be used
- # to serialize and deserialize a \Symbol object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Symbol#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/symbol'
- # x = :foo.as_json
- # # => {"json_class"=>"Symbol", "s"=>"foo"}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object:
- #
- # Symbol.json_create(x) # => :foo
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 's' => to_s,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/symbol'
- # puts :foo.to_json
- #
- # Output:
- #
- # # {"json_class":"Symbol","s":"foo"}
- #
- def to_json(state = nil, *a)
- state = ::JSON::State.from_state(state)
- if state.strict?
- super
- else
- as_json.to_json(state, *a)
- end
- end
-
- # See #as_json.
- def self.json_create(o)
- o['s'].to_sym
- end
-end
diff --git a/lib/json/add/time.rb b/lib/json/add/time.rb
deleted file mode 100644
index 05a1f242f..000000000
--- a/lib/json/add/time.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
- require 'json'
-end
-
-class Time
-
- # See #as_json.
- def self.json_create(object)
- if usec = object.delete('u') # used to be tv_usec -> tv_nsec
- object['n'] = usec * 1000
- end
- at(object['s'], Rational(object['n'], 1000))
- end
-
- # Methods Time#as_json and +Time.json_create+ may be used
- # to serialize and deserialize a \Time object;
- # see Marshal[https://docs.ruby-lang.org/en/master/Marshal.html].
- #
- # \Method Time#as_json serializes +self+,
- # returning a 2-element hash representing +self+:
- #
- # require 'json/add/time'
- # x = Time.now.as_json
- # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644}
- #
- # \Method +JSON.create+ deserializes such a hash, returning a \Time object:
- #
- # Time.json_create(x)
- # # => 2023-11-25 11:00:56.472846644 -0600
- #
- def as_json(*)
- {
- JSON.create_id => self.class.name,
- 's' => tv_sec,
- 'n' => tv_nsec,
- }
- end
-
- # Returns a JSON string representing +self+:
- #
- # require 'json/add/time'
- # puts Time.now.to_json
- #
- # Output:
- #
- # {"json_class":"Time","s":1700931678,"n":980650786}
- #
- def to_json(*args)
- as_json.to_json(*args)
- end
-end
diff --git a/lib/json/common.rb b/lib/json/common.rb
index fdcb860db..6f1176156 100644
--- a/lib/json/common.rb
+++ b/lib/json/common.rb
@@ -17,10 +17,6 @@ def prepare(opts)
opts[:on_load] = on_load
end
- if opts.fetch(:create_additions, false) != false
- opts = create_additions_proc(opts)
- end
-
opts
end
@@ -47,77 +43,10 @@ def array_class_proc(array_class, on_load)
on_load.nil? ? obj : on_load.call(obj)
end
end
-
- # TODO: extract :create_additions support to another gem for version 3.0
- def create_additions_proc(opts)
- if opts[:symbolize_names]
- raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
- end
-
- opts = opts.dup
- create_additions = opts.fetch(:create_additions, false)
- on_load = opts[:on_load]
- object_class = opts[:object_class] || Hash
-
- opts[:on_load] = ->(object) do
- case object
- when String
- opts[:match_string]&.each do |pattern, klass|
- if match = pattern.match(object)
- create_additions_warning if create_additions.nil?
- object = klass.json_create(object)
- break
- end
- end
- when object_class
- if opts[:create_additions] != false
- if class_path = object[JSON.create_id]
- klass = begin
- Object.const_get(class_path)
- rescue NameError => e
- raise ArgumentError, "can't get const #{class_path}: #{e}"
- end
-
- if klass.respond_to?(:json_creatable?) ? klass.json_creatable? : klass.respond_to?(:json_create)
- create_additions_warning if create_additions.nil?
- object = klass.json_create(object)
- end
- end
- end
- end
-
- on_load.nil? ? object : on_load.call(object)
- end
-
- opts
- end
-
- def create_additions_warning
- JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
- "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
- "pass `create_additions: true`"
- end
end
end
class << self
- def deprecation_warning(message, uplevel = 3) # :nodoc:
- gem_root = File.expand_path("..", __dir__) + "/"
- caller_locations(uplevel, 10).each do |frame|
- if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
- uplevel += 1
- else
- break
- end
- end
-
- if RUBY_VERSION >= "3.0"
- warn(message, uplevel: uplevel, category: :deprecated)
- else
- warn(message, uplevel: uplevel)
- end
- end
-
# :call-seq:
# JSON[object] -> new_array or new_string
#
@@ -193,44 +122,18 @@ def generator=(generator) # :nodoc:
private
# Called from the extension when a hash has both string and symbol keys
- def on_mixed_keys_hash(hash, do_raise)
+ def on_mixed_keys_hash(hash)
set = {}
hash.each_key do |key|
key_str = key.to_s
if set[key_str]
- message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
- if do_raise
- raise GeneratorError, message
- else
- deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
- end
+ raise GeneratorError, "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
else
set[key_str] = true
end
end
end
-
- def deprecated_singleton_attr_accessor(*attrs)
- args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
- attrs.each do |attr|
- singleton_class.class_eval <<~RUBY
- def #{attr}
- warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
- @#{attr}
- end
-
- def #{attr}=(val)
- warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
- @#{attr} = val
- end
-
- def _#{attr}
- @#{attr}
- end
- RUBY
- end
- end
end
# Sets create identifier, which is used to decide if the _json_create_
@@ -455,28 +358,6 @@ def generate(obj, opts = nil)
end
end
- # :call-seq:
- # JSON.fast_generate(obj, opts) -> new_string
- #
- # Arguments +obj+ and +opts+ here are the same as
- # arguments +obj+ and +opts+ in JSON.generate.
- #
- # By default, generates \JSON data without checking
- # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled).
- #
- # Raises an exception if +obj+ contains circular references:
- # a = []; b = []; a.push(b); b.push(a)
- # # Raises SystemStackError (stack level too deep):
- # JSON.fast_generate(a)
- def fast_generate(obj, opts = nil)
- if RUBY_VERSION >= "3.0"
- warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
- else
- warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
- end
- generate(obj, opts)
- end
-
PRETTY_GENERATE_OPTIONS = {
indent: ' ',
space: ' ',
@@ -536,30 +417,6 @@ def pretty_generate(obj, opts = nil)
State.generate(obj, options, nil)
end
- # Sets or returns default options for the JSON.unsafe_load method.
- # Initially:
- # opts = JSON.load_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
- deprecated_singleton_attr_accessor :unsafe_load_default_options
-
- @unsafe_load_default_options = {
- :max_nesting => false,
- :allow_nan => true,
- :allow_blank => true,
- :create_additions => true,
- }
-
- # Sets or returns default options for the JSON.load method.
- # Initially:
- # opts = JSON.load_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
- deprecated_singleton_attr_accessor :load_default_options
-
- @load_default_options = {
- :allow_nan => true,
- :allow_blank => true,
- :create_additions => nil,
- }
# :call-seq:
# JSON.unsafe_load(source, options = {}) -> object
# JSON.unsafe_load(source, proc = nil, options = {}) -> object
@@ -586,7 +443,6 @@ def pretty_generate(obj, opts = nil)
# See details below.
# - Argument +opts+, if given, contains a \Hash of options for the parsing.
# See {Parsing Options}[#module-JSON-label-Parsing+Options].
- # The default options can be changed via method JSON.unsafe_load_default_options=.
#
# ---
#
@@ -692,17 +548,17 @@ def pretty_generate(obj, opts = nil)
# @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
#
def unsafe_load(source, proc = nil, options = nil)
- opts = if options.nil?
- if proc && proc.is_a?(Hash)
- options, proc = proc, nil
- options
- else
- _unsafe_load_default_options
- end
- else
- _unsafe_load_default_options.merge(options)
+ opts = {
+ max_nesting: false,
+ allow_nan: true,
+ allow_blank: true,
+ }
+ if options.nil? && proc && proc.is_a?(Hash)
+ options, proc = proc, nil
end
+ opts.merge!(options) unless options.nil?
+
unless source.is_a?(String)
if source.respond_to? :to_str
source = source.to_str
@@ -731,16 +587,6 @@ def unsafe_load(source, proc = nil, options = nil)
#
# Returns the Ruby objects created by parsing the given +source+.
#
- # BEWARE: This method is meant to serialise data from trusted user input,
- # like from your own database server or clients under your control, it could
- # be dangerous to allow untrusted users to pass JSON sources into it.
- # If you must use it, use JSON.unsafe_load instead to make it clear.
- #
- # Since JSON version 2.8.0, `load` emits a deprecation warning when a
- # non native type is deserialized, without `create_additions` being explicitly
- # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled
- # by default.
- #
# - Argument +source+ must be, or be convertible to, a \String:
# - If +source+ responds to instance method +to_str+,
# source.to_str becomes the source.
@@ -757,7 +603,6 @@ def unsafe_load(source, proc = nil, options = nil)
# See details below.
# - Argument +opts+, if given, contains a \Hash of options for the parsing.
# See {Parsing Options}[#module-JSON-label-Parsing+Options].
- # The default options can be changed via method JSON.load_default_options=.
#
# ---
#
@@ -868,16 +713,12 @@ def load(source, proc = nil, options = nil)
proc = nil
end
- opts = if options.nil?
- if proc && proc.is_a?(Hash)
- options, proc = proc, nil
- options
- else
- _load_default_options
- end
- else
- _load_default_options.merge(options)
- end
+ opts = {
+ allow_nan: true,
+ allow_blank: true,
+ }
+
+ opts.merge!(options) unless options.nil?
unless source.is_a?(String)
if source.respond_to? :to_str
@@ -901,16 +742,6 @@ def load(source, proc = nil, options = nil)
parse(source, opts)
end
- # Sets or returns the default options for the JSON.dump method.
- # Initially:
- # opts = JSON.dump_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true}
- deprecated_singleton_attr_accessor :dump_default_options
- @dump_default_options = {
- :max_nesting => false,
- :allow_nan => true,
- }
-
# :call-seq:
# JSON.dump(obj, io = nil, limit = nil)
#
@@ -959,9 +790,12 @@ def dump(obj, anIO = nil, limit = nil, kwargs = nil)
end
end
- opts = JSON._dump_default_options
- opts = opts.merge(:max_nesting => limit) if limit
- opts = opts.merge(kwargs) if kwargs
+ opts = {
+ max_nesting: false,
+ allow_nan: true,
+ max_nesting: limit,
+ }
+ opts.merge!(kwargs) if kwargs
begin
State.generate(obj, opts, anIO)
@@ -970,68 +804,6 @@ def dump(obj, anIO = nil, limit = nil, kwargs = nil)
end
end
- # :stopdoc:
- # All these were meant to be deprecated circa 2009, but were just set as undocumented
- # so usage still exist in the wild.
- def unparse(...)
- if RUBY_VERSION >= "3.0"
- warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
- else
- warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
- end
- generate(...)
- end
- module_function :unparse
-
- def fast_unparse(...)
- if RUBY_VERSION >= "3.0"
- warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
- else
- warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
- end
- generate(...)
- end
- module_function :fast_unparse
-
- def pretty_unparse(...)
- if RUBY_VERSION >= "3.0"
- warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
- else
- warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
- end
- pretty_generate(...)
- end
- module_function :fast_unparse
-
- def restore(...)
- if RUBY_VERSION >= "3.0"
- warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
- else
- warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
- end
- load(...)
- end
- module_function :restore
-
- class << self
- private
-
- def const_missing(const_name)
- case const_name
- when :PRETTY_STATE_PROTOTYPE
- if RUBY_VERSION >= "3.0"
- warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
- else
- warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
- end
- state.new(PRETTY_GENERATE_OPTIONS)
- else
- super
- end
- end
- end
- # :startdoc:
-
# JSON::Coder holds a parser and generator configuration.
#
# module MyApp
@@ -1136,36 +908,6 @@ def to_json(state = nil, *)
module ::Kernel
private
- # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
- # one line.
- def j(*objs)
- if RUBY_VERSION >= "3.0"
- warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
- else
- warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
- end
-
- objs.each do |obj|
- puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
- end
- nil
- end
-
- # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
- # indentation and over many lines.
- def jj(*objs)
- if RUBY_VERSION >= "3.0"
- warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
- else
- warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
- end
-
- objs.each do |obj|
- puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
- end
- nil
- end
-
# If _object_ is string-like, parse the string and return the parsed result as
# a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
# structure object and return it.
diff --git a/lib/json/ext/generator/state.rb b/lib/json/ext/generator/state.rb
index 3c1d2fb94..a9578b9bd 100644
--- a/lib/json/ext/generator/state.rb
+++ b/lib/json/ext/generator/state.rb
@@ -71,33 +71,6 @@ def to_h
end
alias_method :to_hash, :to_h
-
- # call-seq: [](name)
- #
- # Returns the value returned by method +name+.
- def [](name)
- ::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
-
- if respond_to?(name)
- __send__(name)
- else
- instance_variable_get("@#{name}") if
- instance_variables.include?("@#{name}".to_sym) # avoid warning
- end
- end
-
- # call-seq: []=(name, value)
- #
- # Sets the attribute name to value.
- def []=(name, value)
- ::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
-
- if respond_to?(name_writer = "#{name}=")
- __send__ name_writer, value
- else
- instance_variable_set "@#{name}", value
- end
- end
end
end
end
diff --git a/lib/json/generic_object.rb b/lib/json/generic_object.rb
deleted file mode 100644
index 5c8ace354..000000000
--- a/lib/json/generic_object.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-begin
- require 'ostruct'
-rescue LoadError
- warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
-end
-
-module JSON
- class GenericObject < OpenStruct
- class << self
- alias [] new
-
- def json_creatable?
- @json_creatable
- end
-
- attr_writer :json_creatable
-
- def json_create(data)
- data = data.dup
- data.delete JSON.create_id
- self[data]
- end
-
- def from_hash(object)
- case
- when object.respond_to?(:to_hash)
- result = new
- object.to_hash.each do |key, value|
- result[key] = from_hash(value)
- end
- result
- when object.respond_to?(:to_ary)
- object.to_ary.map { |a| from_hash(a) }
- else
- object
- end
- end
-
- def load(source, proc = nil, opts = {})
- result = ::JSON.load(source, proc, opts.merge(:object_class => self))
- result.nil? ? new : result
- end
-
- def dump(obj, *args)
- ::JSON.dump(obj, *args)
- end
- end
- self.json_creatable = false
-
- def to_hash
- table
- end
-
- def |(other)
- self.class[other.to_hash.merge(to_hash)]
- end
-
- def as_json(*)
- { JSON.create_id => self.class.name }.merge to_hash
- end
-
- def to_json(*a)
- as_json.to_json(*a)
- end
- end if defined?(::OpenStruct)
-end
diff --git a/lib/json/truffle_ruby/generator.rb b/lib/json/truffle_ruby/generator.rb
index ee6186fbe..495167be2 100644
--- a/lib/json/truffle_ruby/generator.rb
+++ b/lib/json/truffle_ruby/generator.rb
@@ -167,6 +167,7 @@ def initialize(opts = nil)
@strict = false
@max_nesting = 100
@sort_keys = false
+ @allow_duplicate_key = false
configure(opts) if opts
end
@@ -318,6 +319,7 @@ def configure(opts)
self.sort_keys = opts[:sort_keys] if opts.key?(:sort_keys)
@depth = opts[:depth] || 0
@buffer_initial_length ||= opts[:buffer_initial_length]
+ @allow_duplicate_key = !!opts[:allow_duplicate_key]
@script_safe = if opts.key?(:script_safe)
!!opts[:script_safe]
@@ -327,12 +329,6 @@ def configure(opts)
false
end
- if opts.key?(:allow_duplicate_key)
- @allow_duplicate_key = !!opts[:allow_duplicate_key]
- else
- @allow_duplicate_key = nil # nil is deprecation
- end
-
@strict = !!opts[:strict] if opts.key?(:strict)
if !opts.key?(:max_nesting) # defaults to 100
@@ -362,10 +358,6 @@ def to_h
result[key.to_sym] = instance_variable_get(iv)
end
- if result[:allow_duplicate_key].nil?
- result.delete(:allow_duplicate_key)
- end
-
result
end
@@ -416,7 +408,7 @@ def generate(obj, anIO = nil)
else
if key_type && !@allow_duplicate_key && key_type != k.class
key_type = nil # stop checking
- JSON.send(:on_mixed_keys_hash, obj, !@allow_duplicate_key.nil?)
+ JSON.send(:on_mixed_keys_hash, obj)
end
buf << ','
end
@@ -483,28 +475,6 @@ def generate(obj, anIO = nil)
end
buf << '"'
end
-
- # Return the value returned by method +name+.
- def [](name)
- ::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
-
- if respond_to?(name)
- __send__(name)
- else
- instance_variable_get("@#{name}") if
- instance_variables.include?("@#{name}".to_sym) # avoid warning
- end
- end
-
- def []=(name, value)
- ::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
-
- if respond_to?(name_writer = "#{name}=")
- __send__ name_writer, value
- else
- instance_variable_set "@#{name}", value
- end
- end
end
module GeneratorMethods
@@ -569,7 +539,7 @@ def json_transform(state)
else
if key_type && !state.allow_duplicate_key? && key_type != key.class
key_type = nil # stop checking
- JSON.send(:on_mixed_keys_hash, self, state.allow_duplicate_key? == false)
+ JSON.send(:on_mixed_keys_hash, self)
end
result << delim
end
diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb
deleted file mode 100644
index 4d8d18687..000000000
--- a/test/json/json_addition_test.rb
+++ /dev/null
@@ -1,192 +0,0 @@
-# frozen_string_literal: true
-require_relative 'test_helper'
-require 'json/add/core'
-require 'json/add/complex'
-require 'json/add/rational'
-require 'json/add/bigdecimal'
-require 'json/add/ostruct'
-require 'json/add/set'
-require 'date'
-
-class JSONAdditionTest < Test::Unit::TestCase
- include JSON
-
- class A
- def initialize(a)
- @a = a
- end
-
- attr_reader :a
-
- def ==(other)
- a == other.a
- end
-
- def self.json_create(object)
- new(*object['args'])
- end
-
- def to_json(*args)
- {
- 'json_class' => self.class.name,
- 'args' => [ @a ],
- }.to_json(*args)
- end
- end
-
- class A2 < A
- def to_json(*args)
- {
- 'json_class' => self.class.name,
- 'args' => [ @a ],
- }.to_json(*args)
- end
- end
-
- class B
- def to_json(*args)
- {
- 'json_class' => self.class.name,
- }.to_json(*args)
- end
- end
-
- class C
- def to_json(*args)
- {
- 'json_class' => 'JSONAdditionTest::Nix',
- }.to_json(*args)
- end
- end
-
- def test_extended_json
- a = A.new(666)
- json = generate(a)
- a_again = parse(json, :create_additions => true)
- assert_kind_of a.class, a_again
- assert_equal a, a_again
- end
-
- def test_extended_json_default
- a = A.new(666)
- assert A.respond_to?(:json_create)
- json = generate(a)
- a_hash = parse(json)
- assert_kind_of Hash, a_hash
- end
-
- def test_extended_json_disabled
- a = A.new(666)
- json = generate(a)
- a_again = parse(json, :create_additions => true)
- assert_kind_of a.class, a_again
- assert_equal a, a_again
- a_hash = parse(json, :create_additions => false)
- assert_kind_of Hash, a_hash
- assert_equal(
- {"args"=>[666], "json_class"=>"JSONAdditionTest::A"}.sort_by { |k,| k },
- a_hash.sort_by { |k,| k }
- )
- end
-
- def test_extended_json_fail1
- b = B.new
- json = generate(b)
- assert_equal({ "json_class"=>"JSONAdditionTest::B" }, parse(json))
- end
-
- def test_extended_json_fail2
- c = C.new
- json = generate(c)
- assert_raise(ArgumentError, NameError) { parse(json, :create_additions => true) }
- end
-
- def test_raw_strings
- raw = ''.b
- raw_array = []
- for i in 0..255
- raw << i
- raw_array << i
- end
- json = raw.to_json_raw
- json_raw_object = raw.to_json_raw_object
- hash = { 'json_class' => 'String', 'raw'=> raw_array }
- assert_equal hash, json_raw_object
- assert_match(/\A\{.*\}\z/, json)
- assert_match(/"json_class":"String"/, json)
- assert_match(/"raw":\[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\]/, json)
- raw_again = parse(json, :create_additions => true)
- assert_equal raw, raw_again
- end
-
- MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
-
- def test_core
- t = Time.now
- assert_equal t, JSON(JSON(t), :create_additions => true)
- d = Date.today
- assert_equal d, JSON(JSON(d), :create_additions => true)
- d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
- assert_equal d, JSON(JSON(d), :create_additions => true)
- assert_equal 1..10, JSON(JSON(1..10), :create_additions => true)
- assert_equal 1...10, JSON(JSON(1...10), :create_additions => true)
- assert_equal "a".."c", JSON(JSON("a".."c"), :create_additions => true)
- assert_equal "a"..."c", JSON(JSON("a"..."c"), :create_additions => true)
- s = MyJsonStruct.new 4711, 'foot'
- assert_equal s, JSON(JSON(s), :create_additions => true)
- struct = Struct.new :foo, :bar
- s = struct.new 4711, 'foot'
- assert_raise(JSONError) { JSON(s) }
- begin
- raise TypeError, "test me"
- rescue TypeError => e
- e_json = JSON.generate e
- e_again = JSON e_json, :create_additions => true
- assert_kind_of TypeError, e_again
- assert_equal e.message, e_again.message
- assert_equal e.backtrace, e_again.backtrace
- end
- assert_equal(/foo/, JSON(JSON(/foo/), :create_additions => true))
- assert_equal(/foo/i, JSON(JSON(/foo/i), :create_additions => true))
- end
-
- def test_deprecated_load_create_additions
- assert_deprecated_warning(/use JSON\.unsafe_load/) do
- JSON.load(JSON.dump(Time.now))
- end
- end
-
- def test_utc_datetime
- now = Time.now
- d = DateTime.parse(now.to_s) # usual case
- assert_equal d, parse(d.to_json, :create_additions => true)
- d = DateTime.parse(now.utc.to_s) # of = 0
- assert_equal d, parse(d.to_json, :create_additions => true)
- d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
- assert_equal d, parse(d.to_json, :create_additions => true)
- d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
- assert_equal d, parse(d.to_json, :create_additions => true)
- end
-
- def test_rational_complex
- assert_equal Rational(2, 9), parse(JSON(Rational(2, 9)), :create_additions => true)
- assert_equal Complex(2, 9), parse(JSON(Complex(2, 9)), :create_additions => true)
- end
-
- def test_bigdecimal
- assert_equal BigDecimal('3.141', 23), JSON(JSON(BigDecimal('3.141', 23)), :create_additions => true)
- assert_equal BigDecimal('3.141', 666), JSON(JSON(BigDecimal('3.141', 666)), :create_additions => true)
- end if defined?(::BigDecimal)
-
- def test_ostruct
- o = OpenStruct.new
- # XXX this won't work; o.foo = { :bar => true }
- o.foo = { 'bar' => true }
- assert_equal o, parse(JSON(o), :create_additions => true)
- end if defined?(::OpenStruct)
-
- def test_set
- s = Set.new([:a, :b, :c, :a])
- assert_equal s, JSON.parse(JSON(s), :create_additions => true)
- end
-end
diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb
index 37568b556..72b8f390a 100644
--- a/test/json/json_common_interface_test.rb
+++ b/test/json/json_common_interface_test.rb
@@ -271,12 +271,6 @@ def test_dump_in_io
assert_equal JSON.dump(big_object), io.string
end
- def test_dump_should_modify_defaults
- max_nesting = JSON._dump_default_options[:max_nesting]
- dump([], StringIO.new, 10)
- assert_equal max_nesting, JSON._dump_default_options[:max_nesting]
- end
-
def test_JSON
assert_equal @json, JSON(@hash)
assert_equal @json, JSON(@hash_with_method_missing)
@@ -315,12 +309,6 @@ def test_load_file_with_bad_default_external_encoding
end
end
- def test_deprecated_dump_default_options
- assert_deprecated_warning(/dump_default_options/) do
- JSON.dump_default_options
- end
- end
-
private
def with_external_encoding(encoding)
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index ab19704b1..f124e22b6 100755
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -256,20 +256,6 @@ def test_generate_custom
JSON
end
- def test_fast_generate
- assert_deprecated_warning(/fast_generate/) do
- json = fast_generate(@hash)
- assert_equal(parse(@json2), parse(json))
- parsed_json = parse(json)
- assert_equal(@hash, parsed_json)
- json = fast_generate({1=>2})
- assert_equal('{"1":2}', json)
- parsed_json = parse(json)
- assert_equal({"1"=>2}, parsed_json)
- assert_equal '666', fast_generate(666)
- end
- end
-
def test_own_state
state = State.new
json = generate(@hash, state)
@@ -287,10 +273,6 @@ def test_states
json = generate({1=>2}, nil)
assert_equal('{"1":2}', json)
s = JSON.state.new
- assert s.check_circular?
- assert_deprecated_warning(/JSON::State/) do
- assert s[:check_circular?]
- end
h = { 1=>2 }
h[3] = h
assert_raise(JSON::NestingError) { generate(h) }
@@ -299,10 +281,6 @@ def test_states
a = [ 1, 2 ]
a << a
assert_raise(JSON::NestingError) { generate(a, s) }
- assert s.check_circular?
- assert_deprecated_warning(/JSON::State/) do
- assert s[:check_circular?]
- end
end
def test_falsy_state
@@ -329,6 +307,7 @@ def test_falsy_state
def test_state_defaults
state = JSON::State.new
assert_equal({
+ :allow_duplicate_key => false,
:allow_nan => false,
:array_nl => "",
:as_json => false,
@@ -366,26 +345,24 @@ def test_state_defaults
end
def test_allow_nan
- assert_deprecated_warning(/fast_generate/) do
- error = assert_raise(GeneratorError) { generate([JSON::NaN]) }
- assert_same JSON::NaN, error.invalid_object
- assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
- assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
- assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
- assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
- error = assert_raise(GeneratorError) { generate([JSON::Infinity]) }
- assert_same JSON::Infinity, error.invalid_object
- assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
- assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
- assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
- assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
- error = assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
- assert_same JSON::MinusInfinity, error.invalid_object
- assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
- assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
- assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
- assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
- end
+ error = assert_raise(GeneratorError) { generate([JSON::NaN]) }
+ assert_same JSON::NaN, error.invalid_object
+ assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
+ assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
+ error = assert_raise(GeneratorError) { generate([JSON::Infinity]) }
+ assert_same JSON::Infinity, error.invalid_object
+ assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
+ assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
+ error = assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
+ assert_same JSON::MinusInfinity, error.invalid_object
+ assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
+ assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
end
# An object that changes state.depth when it receives to_json(state)
@@ -577,35 +554,6 @@ def to_s
bignum.class.define_method(:to_s, original_to_s) if original_to_s
end
- def test_hash_likeness_set_symbol
- assert_deprecated_warning(/JSON::State/) do
- state = JSON.state.new
- assert_equal nil, state[:foo]
- assert_equal nil.class, state[:foo].class
- assert_equal nil, state['foo']
- state[:foo] = :bar
- assert_equal :bar, state[:foo]
- assert_equal :bar, state['foo']
- state_hash = state.to_hash
- assert_kind_of Hash, state_hash
- assert_equal :bar, state_hash[:foo]
- end
- end
-
- def test_hash_likeness_set_string
- assert_deprecated_warning(/JSON::State/) do
- state = JSON.state.new
- assert_equal nil, state[:foo]
- assert_equal nil, state['foo']
- state['foo'] = :bar
- assert_equal :bar, state[:foo]
- assert_equal :bar, state['foo']
- state_hash = state.to_hash
- assert_kind_of Hash, state_hash
- assert_equal :bar, state_hash[:foo]
- end
- end
-
def test_json_state_to_h_roundtrip
state = JSON.state.new
assert_equal state.to_h, JSON.state.new(state.to_h).to_h
@@ -1090,13 +1038,6 @@ def test_generate_duplicate_keys_allowed
assert_equal %({"foo":1,"foo":2}), JSON.generate(hash, allow_duplicate_key: true)
end
- def test_generate_duplicate_keys_deprecated
- hash = { foo: 1, "foo" => 2 }
- assert_deprecated_warning(/allow_duplicate_key/) do
- assert_equal %({"foo":1,"foo":2}), JSON.generate(hash)
- end
- end
-
def test_generate_duplicate_keys_disallowed
hash = { foo: 1, "foo" => 2 }
error = assert_raise JSON::GeneratorError do
diff --git a/test/json/json_generic_object_test.rb b/test/json/json_generic_object_test.rb
deleted file mode 100644
index 57e3bf3c5..000000000
--- a/test/json/json_generic_object_test.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-require_relative 'test_helper'
-
-# ostruct is required to test JSON::GenericObject
-begin
- require "ostruct"
-rescue LoadError
- return
-end
-
-class JSONGenericObjectTest < Test::Unit::TestCase
- def setup
- if defined?(JSON::GenericObject)
- @go = JSON::GenericObject[ :a => 1, :b => 2 ]
- else
- omit("JSON::GenericObject is not available")
- end
- end
-
- def test_attributes
- assert_equal 1, @go.a
- assert_equal 1, @go[:a]
- assert_equal 2, @go.b
- assert_equal 2, @go[:b]
- assert_nil @go.c
- assert_nil @go[:c]
- end
-
- def test_generate_json
- switch_json_creatable do
- assert_equal @go, JSON(JSON(@go), :create_additions => true)
- end
- end
-
- def test_parse_json
- assert_kind_of Hash,
- JSON(
- '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
- :create_additions => true
- )
- switch_json_creatable do
- assert_equal @go, l =
- JSON(
- '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
- :create_additions => true
- )
- assert_equal 1, l.a
- assert_equal @go,
- l = JSON('{ "a": 1, "b": 2 }', :object_class => JSON::GenericObject)
- assert_equal 1, l.a
- assert_equal JSON::GenericObject[:a => JSON::GenericObject[:b => 2]],
- l = JSON('{ "a": { "b": 2 } }', :object_class => JSON::GenericObject)
- assert_equal 2, l.a.b
- end
- end
-
- def test_from_hash
- result = JSON::GenericObject.from_hash(
- :foo => { :bar => { :baz => true }, :quux => [ { :foobar => true } ] })
- assert_kind_of JSON::GenericObject, result.foo
- assert_kind_of JSON::GenericObject, result.foo.bar
- assert_equal true, result.foo.bar.baz
- assert_kind_of JSON::GenericObject, result.foo.quux.first
- assert_equal true, result.foo.quux.first.foobar
- assert_equal true, JSON::GenericObject.from_hash(true)
- end
-
- def test_json_generic_object_load
- empty = JSON::GenericObject.load(nil)
- assert_kind_of JSON::GenericObject, empty
- simple_json = '{"json_class":"JSON::GenericObject","hello":"world"}'
- simple = JSON::GenericObject.load(simple_json)
- assert_kind_of JSON::GenericObject, simple
- assert_equal "world", simple.hello
- converting = JSON::GenericObject.load('{ "hello": "world" }')
- assert_kind_of JSON::GenericObject, converting
- assert_equal "world", converting.hello
-
- json = JSON::GenericObject.dump(JSON::GenericObject[:hello => 'world'])
- assert_equal JSON(json), JSON('{"json_class":"JSON::GenericObject","hello":"world"}')
- end
-
- private
-
- def switch_json_creatable
- JSON::GenericObject.json_creatable = true
- yield
- ensure
- JSON::GenericObject.json_creatable = false
- end
-end
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index 2f79b87cc..1ce8031a8 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -405,35 +405,16 @@ def test_parse_escaped_key
def test_parse_duplicate_key
expected = {"a" => 2}
- expected_sym = {a: 2}
assert_equal expected, parse('{"a": 1, "a": 2}', allow_duplicate_key: true)
assert_raise(ParserError) { parse('{"a": 1, "a": 2}', allow_duplicate_key: false) }
assert_raise(ParserError) { parse('{"a": 1, "a": 2}', allow_duplicate_key: false, symbolize_names: true) }
- assert_deprecated_warning(/duplicate key "a"/) do
- assert_equal expected, parse('{"a": 1, "a": 2}')
- end
- assert_deprecated_warning(/duplicate key "a"/) do
- assert_equal expected_sym, parse('{"a": 1, "a": 2}', symbolize_names: true)
- end
-
- if RUBY_ENGINE == 'ruby'
- assert_deprecated_warning(/#{File.basename(__FILE__)}\:#{__LINE__ + 1}/) do
- assert_equal expected, parse('{"a": 1, "a": 2}')
- end
- end
-
unless RUBY_ENGINE == 'jruby'
assert_raise(ParserError) do
fake_key = Object.new
JSON.load('{"a": 1, "a": 2}', -> (obj) { obj == "a" ? fake_key : obj }, allow_duplicate_key: false)
end
-
- assert_deprecated_warning(/duplicate key # (obj) { obj == "a" ? fake_key : obj })
- end
end
end
@@ -465,9 +446,6 @@ def test_symbolize_names
parse('{"foo":"bar", "baz":"quux"}'))
assert_equal({ :foo => "bar", :baz => "quux" },
parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
- assert_raise(ArgumentError) do
- parse('{}', :symbolize_names => true, :create_additions => true)
- end
end
def test_freeze
@@ -531,16 +509,8 @@ def test_parse_comments
assert_raise(ParserError) { parse('{} /*/', allow_comments: true) }
assert_raise(ParserError) { parse('{} /x wrong comment', allow_comments: true) }
assert_raise(ParserError) { parse('{} /', allow_comments: true) }
- end
-
- def test_parse_comments_deprecation
assert_equal({}, parse('/**/ {}', allow_comments: true))
assert_raise(ParserError) { parse('/**/ {}', allow_comments: false) }
- if RUBY_ENGINE == 'ruby'
- assert_deprecated_warning(/Encountered comment in JSON/) do
- parse('/**/ {}')
- end
- end
end
def test_nesting
@@ -809,18 +779,6 @@ def test_parse_generic_object
end
end
- def test_generate_core_subclasses_with_new_to_json
- obj = SubHash2["foo" => SubHash2["bar" => true]]
- obj_json = JSON(obj)
- obj_again = parse(obj_json, :create_additions => true)
- assert_kind_of SubHash2, obj_again
- assert_kind_of SubHash2, obj_again['foo']
- assert obj_again['foo']['bar']
- assert_equal obj, obj_again
- assert_equal ["foo"],
- JSON(JSON(SubArray2["foo"]), :create_additions => true)
- end
-
def test_generate_core_subclasses_with_default_to_json
assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"])
assert_equal '["foo"]', JSON(SubArray["foo"])
diff --git a/test/json/json_string_matching_test.rb b/test/json/json_string_matching_test.rb
deleted file mode 100644
index 21cd64902..000000000
--- a/test/json/json_string_matching_test.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-require_relative 'test_helper'
-require 'time'
-
-class JSONStringMatchingTest < Test::Unit::TestCase
- include JSON
-
- class TestTime < ::Time
- def self.json_create(string)
- Time.parse(string)
- end
-
- def to_json(*)
- %{"#{strftime('%FT%T%z')}"}
- end
-
- def ==(other)
- to_i == other.to_i
- end
- end
-
- def test_match_date
- t = TestTime.new
- t_json = [ t ].to_json
- time_regexp = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/
- assert_equal [ t ],
- parse(
- t_json,
- :create_additions => true,
- :match_string => { time_regexp => TestTime }
- )
- assert_equal [ t.strftime('%FT%T%z') ],
- parse(
- t_json,
- :match_string => { time_regexp => TestTime }
- )
- end
-end