[ruby/json] Deprecate all *_default_options

Globally changing the behavior of the library is a bad idea, as
many different libraries may rely on `json` and may not expect it
and likely never tested that a different default config works for them.

If you need to change the behavior of JSON, it's best to do it only
locally, and not globally.

In addition the new `JSON::Coder` interface is much more suited for
that.

Another reason for the deprecation is that it's impossible to
make `JSON.load` and `JSON.dump` Ractor-safe with such API.

https://github.com/ruby/json/commit/172762c6e4
This commit is contained in:
Jean Boussier 2025-03-26 11:47:51 +01:00 committed by Hiroshi SHIBATA
parent 46ee73f4f6
commit f4529ecbe7
2 changed files with 54 additions and 31 deletions

View File

@ -101,6 +101,29 @@ module JSON
# Sets or Returns the JSON generator state class that is used by JSON. # Sets or Returns the JSON generator state class that is used by JSON.
attr_accessor :state attr_accessor :state
private
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 end
# Sets create identifier, which is used to decide if the _json_create_ # Sets create identifier, which is used to decide if the _json_create_
@ -424,28 +447,26 @@ module JSON
module_function :pretty_unparse module_function :pretty_unparse
# :startdoc: # :startdoc:
class << self
# Sets or returns default options for the JSON.unsafe_load method. # Sets or returns default options for the JSON.unsafe_load method.
# Initially: # Initially:
# opts = JSON.load_default_options # opts = JSON.load_default_options
# opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
attr_accessor :unsafe_load_default_options deprecated_singleton_attr_accessor :unsafe_load_default_options
end
self.unsafe_load_default_options = { @unsafe_load_default_options = {
:max_nesting => false, :max_nesting => false,
:allow_nan => true, :allow_nan => true,
:allow_blank => true, :allow_blank => true,
:create_additions => true, :create_additions => true,
} }
class << self
# Sets or returns default options for the JSON.load method. # Sets or returns default options for the JSON.load method.
# Initially: # Initially:
# opts = JSON.load_default_options # opts = JSON.load_default_options
# opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
attr_accessor :load_default_options deprecated_singleton_attr_accessor :load_default_options
end
self.load_default_options = { @load_default_options = {
:allow_nan => true, :allow_nan => true,
:allow_blank => true, :allow_blank => true,
:create_additions => nil, :create_additions => nil,
@ -581,9 +602,9 @@ module JSON
# #
def unsafe_load(source, proc = nil, options = nil) def unsafe_load(source, proc = nil, options = nil)
opts = if options.nil? opts = if options.nil?
unsafe_load_default_options _unsafe_load_default_options
else else
unsafe_load_default_options.merge(options) _unsafe_load_default_options.merge(options)
end end
unless source.is_a?(String) unless source.is_a?(String)
@ -741,9 +762,9 @@ module JSON
# #
def load(source, proc = nil, options = nil) def load(source, proc = nil, options = nil)
opts = if options.nil? opts = if options.nil?
load_default_options _load_default_options
else else
load_default_options.merge(options) _load_default_options.merge(options)
end end
unless source.is_a?(String) unless source.is_a?(String)
@ -781,14 +802,12 @@ module JSON
alias restore load alias restore load
module_function :restore module_function :restore
class << self
# Sets or returns the default options for the JSON.dump method. # Sets or returns the default options for the JSON.dump method.
# Initially: # Initially:
# opts = JSON.dump_default_options # opts = JSON.dump_default_options
# opts # => {:max_nesting=>false, :allow_nan=>true} # opts # => {:max_nesting=>false, :allow_nan=>true}
attr_accessor :dump_default_options deprecated_singleton_attr_accessor :dump_default_options
end @dump_default_options = {
self.dump_default_options = {
:max_nesting => false, :max_nesting => false,
:allow_nan => true, :allow_nan => true,
} }
@ -841,7 +860,7 @@ module JSON
end end
end end
opts = JSON.dump_default_options opts = JSON._dump_default_options
opts = opts.merge(:max_nesting => limit) if limit opts = opts.merge(:max_nesting => limit) if limit
opts = opts.merge(kwargs) if kwargs opts = opts.merge(kwargs) if kwargs

View File

@ -174,9 +174,9 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
end end
def test_dump_should_modify_defaults def test_dump_should_modify_defaults
max_nesting = JSON.dump_default_options[:max_nesting] max_nesting = JSON._dump_default_options[:max_nesting]
dump([], StringIO.new, 10) dump([], StringIO.new, 10)
assert_equal max_nesting, JSON.dump_default_options[:max_nesting] assert_equal max_nesting, JSON._dump_default_options[:max_nesting]
end end
def test_JSON def test_JSON
@ -211,6 +211,10 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
end end
end end
def test_deprecated_dump_default_options
assert JSON.dump_default_options
end
private private
def with_external_encoding(encoding) def with_external_encoding(encoding)