Module: MultiJSON Private

Extended by:
AdapterSelector, Options
Defined in:
lib/multi_json.rb,
lib/multi_json/adapter.rb,
lib/multi_json/options.rb,
lib/multi_json/version.rb,
lib/multi_json/deprecated.rb,
lib/multi_json/adapters/oj.rb,
lib/multi_json/concurrency.rb,
lib/multi_json/parse_error.rb,
lib/multi_json/adapter_error.rb,
lib/multi_json/adapters/yajl.rb,
lib/multi_json/options_cache.rb,
lib/multi_json/options_cache.rb,
lib/multi_json/adapter_selector.rb,
lib/multi_json/adapters/json_gem.rb,
lib/multi_json/adapters/oj_common.rb,
lib/multi_json/adapters/fast_jsonparser.rb,
lib/multi_json/options_cache/mutex_store.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Deprecated public API kept around for one major release

Each method here emits a one-time deprecation warning on first call and delegates to its current-API counterpart. The whole file is loaded by MultiJSON so the deprecation surface stays out of the main module definition.

Defined Under Namespace

Modules: AdapterSelector, Adapters, Concurrency, Options, OptionsCache Classes: Adapter, AdapterError, ParseError, Version

Constant Summary collapse

VERSION =

Current version string in semver format

Version.to_s.freeze
DecodeError =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Legacy aliases for backward compatibility

LoadError = ParseError

Constants included from Options

Options::EMPTY_OPTIONS

Constants included from AdapterSelector

AdapterSelector::REQUIREMENT_MAP

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Options

default_dump_options, default_generate_options, default_load_options, default_parse_options, dump_options, dump_options=, generate_options, generate_options=, load_options, load_options=, parse_options, parse_options=

Methods included from AdapterSelector

default_adapter, default_adapter_excluding

Class Method Details

.adapterClass

Returns the current adapter class

Honors a fiber-local override set by with_adapter so concurrent blocks observe their own adapter without clobbering the process-wide default. Falls back to the process default when no override is set.

Examples:

MultiJSON.adapter  #=> MultiJSON::Adapters::Oj

Returns:

  • (Class)

    the current adapter class



127
128
129
130
131
132
# File 'lib/multi_json.rb', line 127

def adapter
  override = Fiber[:multi_json_adapter]
  return override if override

  @adapter ||= use(nil)
end

.current_adapter(options = {}) ⇒ Class

Returns the adapter to use for the given options

“nil“ is accepted as a no-options sentinel — explicit “current_adapter(nil)“ calls fall through to the process default adapter without raising.

Examples:

MultiJSON.current_adapter(adapter: :oj)  #=> MultiJSON::Adapters::Oj

Parameters:

  • options (Hash, nil) (defaults to: {})

    options that may contain :adapter key, or nil to use the process default

Returns:

  • (Class)

    adapter class



200
201
202
203
204
# File 'lib/multi_json.rb', line 200

def current_adapter(options = {})
  options ||= Options::EMPTY_OPTIONS
  adapter_override = options[:adapter]
  adapter_override ? load_adapter(adapter_override) : adapter
end

.generate(object, options = {}) ⇒ String

Serializes a Ruby object to a JSON string

Examples:

MultiJSON.generate({foo: "bar"})  #=> '{"foo":"bar"}'

Parameters:

  • object (Object)

    object to serialize

  • options (Hash) (defaults to: {})

    serialization options (adapter-specific)

Returns:

  • (String)

    JSON string



214
215
216
# File 'lib/multi_json.rb', line 214

def generate(object, options = {})
  current_adapter(options).dump(object, options)
end

.parse(string, options = {}) ⇒ Object?

Parses a JSON string into a Ruby object

Returns “nil“ for “nil“, empty, and whitespace-only inputs instead of raising. Pass an explicit non-blank string if you want to surface a ParseError for empty payloads at the call site.

Examples:

MultiJSON.parse('{"foo":"bar"}')  #=> {"foo" => "bar"}
MultiJSON.parse("")               #=> nil
MultiJSON.parse("   \n")          #=> nil

Parameters:

  • string (String, #read)

    JSON string or IO-like object

  • options (Hash) (defaults to: {})

    parsing options (adapter-specific)

Returns:

  • (Object, nil)

    parsed Ruby object, or nil for blank input

Raises:

  • (ParseError)

    if parsing fails

  • (AdapterError)

    if the adapter doesn’t define a “ParseError“ constant



178
179
180
181
182
183
184
185
186
# File 'lib/multi_json.rb', line 178

def parse(string, options = {})
  adapter_class = current_adapter(options)
  parse_error_class = MultiJSON.parse_error_class_for(adapter_class)
  begin
    adapter_class.load(string, options)
  rescue parse_error_class => e
    raise ParseError.build(e, string)
  end
end

.parse_error_class_for(adapter_class) ⇒ Class

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolve the “ParseError“ constant for an adapter class

The result is memoized on the adapter class itself in a “@_multi_json_parse_error“ ivar so subsequent “MultiJSON.load“ calls skip the constant lookup entirely. The lookup is performed with “inherit: false“ so a stray top-level “::ParseError“ constant in the host process is correctly ignored on every supported Ruby implementation — TruffleRuby’s “::“ operator walks the ancestor chain and would otherwise pick up the top-level constant. Custom adapters that don’t define their own “ParseError“ get a clear AdapterError instead of the bare “NameError“ Ruby would raise from the rescue clause.

Parameters:

  • adapter_class (Class)

    adapter class to inspect

Returns:

  • (Class)

    the adapter’s ParseError class

Raises:

  • (AdapterError)

    when the adapter doesn’t define ParseError



100
101
102
103
104
105
106
107
108
# File 'lib/multi_json.rb', line 100

def self.parse_error_class_for(adapter_class)
  cached = adapter_class.instance_variable_get(:@_multi_json_parse_error)
  return cached if cached

  resolved = adapter_class.const_get(:ParseError, false)
  adapter_class.instance_variable_set(:@_multi_json_parse_error, resolved)
rescue NameError
  raise AdapterError, "Adapter #{adapter_class} must define a ParseError constant"
end

.use(new_adapter) ⇒ Class Also known as: adapter=

Sets the adapter to use for JSON operations

The merged-options cache is only reset when the new adapter loads successfully. A failed “use(:nonexistent)“ leaves the cache in place so the previously-active adapter keeps its cached entries.

Examples:

MultiJSON.use(:oj)

Parameters:

  • new_adapter (Symbol, String, Module, nil)

    adapter specification

Returns:

  • (Class)

    the loaded adapter class



145
146
147
148
149
150
151
# File 'lib/multi_json.rb', line 145

def use(new_adapter)
  loaded = load_adapter(new_adapter)
  Concurrency.synchronize(:adapter) do
    OptionsCache.reset
    @adapter = loaded
  end
end

.warn_deprecation_once(key, message) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Emit a deprecation warning at most once per process for the given key

Defined as a singleton method (rather than via module_function) so there is exactly one definition for mutation tests to target. Public so the deprecated “load_options“ / “dump_options“ aliases on the Options mixin can invoke it without routing through “MultiJSON.send(…)“.

The warning is tagged with the “:deprecated“ category so callers can silence the whole set with “Warning = false“ or surface it via “ruby -W:deprecated“ — the standard Ruby idiom for library deprecations since 2.7.

Examples:

MultiJSON.warn_deprecation_once(:foo, "MultiJSON.foo is deprecated")

Parameters:

  • key (Symbol)

    identifier for the deprecation (typically the method name)

  • message (String)

    warning message to emit on first call



74
75
76
77
78
79
80
81
# File 'lib/multi_json.rb', line 74

def self.warn_deprecation_once(key, message)
  Concurrency.synchronize(:deprecation_warnings) do
    return if DEPRECATION_WARNINGS_SHOWN.include?(key)

    Kernel.warn(message, category: :deprecated)
    DEPRECATION_WARNINGS_SHOWN.add(key)
  end
end

.with_adapter(new_adapter) { ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instance-method delegate for with_adapter

Examples:

class Foo; include MultiJSON; end
Foo.new.send(:with_adapter, :json_gem) { ... }

Parameters:

  • new_adapter (Symbol, String, Module)

    adapter to use

Yields:

  • block to execute with the temporary adapter

Returns:

  • (Object)

    result of the block



241
242
243
244
245
246
247
# File 'lib/multi_json.rb', line 241

def self.with_adapter(new_adapter)
  previous_override = Fiber[:multi_json_adapter]
  Fiber[:multi_json_adapter] = load_adapter(new_adapter)
  yield
ensure
  Fiber[:multi_json_adapter] = previous_override
end

Instance Method Details

#adapterClass

Returns the current adapter class

Honors a fiber-local override set by with_adapter so concurrent blocks observe their own adapter without clobbering the process-wide default. Falls back to the process default when no override is set.

Examples:

MultiJSON.adapter  #=> MultiJSON::Adapters::Oj

Returns:

  • (Class)

    the current adapter class



127
128
129
130
131
132
# File 'lib/multi_json.rb', line 127

def adapter
  override = Fiber[:multi_json_adapter]
  return override if override

  @adapter ||= use(nil)
end

#adapter=Class

Sets the adapter to use for JSON operations

Examples:

MultiJSON.adapter = :json_gem

Returns:

  • (Class)

    the loaded adapter class



159
# File 'lib/multi_json.rb', line 159

alias_method :adapter=, :use

#current_adapter(options = {}) ⇒ Class

Returns the adapter to use for the given options

“nil“ is accepted as a no-options sentinel — explicit “current_adapter(nil)“ calls fall through to the process default adapter without raising.

Examples:

MultiJSON.current_adapter(adapter: :oj)  #=> MultiJSON::Adapters::Oj

Parameters:

  • options (Hash, nil) (defaults to: {})

    options that may contain :adapter key, or nil to use the process default

Returns:

  • (Class)

    adapter class



200
201
202
203
204
# File 'lib/multi_json.rb', line 200

def current_adapter(options = {})
  options ||= Options::EMPTY_OPTIONS
  adapter_override = options[:adapter]
  adapter_override ? load_adapter(adapter_override) : adapter
end

#generate(object, options = {}) ⇒ String

Serializes a Ruby object to a JSON string

Examples:

MultiJSON.generate({foo: "bar"})  #=> '{"foo":"bar"}'

Parameters:

  • object (Object)

    object to serialize

  • options (Hash) (defaults to: {})

    serialization options (adapter-specific)

Returns:

  • (String)

    JSON string



214
215
216
# File 'lib/multi_json.rb', line 214

def generate(object, options = {})
  current_adapter(options).dump(object, options)
end

#parse(string, options = {}) ⇒ Object?

Parses a JSON string into a Ruby object

Returns “nil“ for “nil“, empty, and whitespace-only inputs instead of raising. Pass an explicit non-blank string if you want to surface a ParseError for empty payloads at the call site.

Examples:

MultiJSON.parse('{"foo":"bar"}')  #=> {"foo" => "bar"}
MultiJSON.parse("")               #=> nil
MultiJSON.parse("   \n")          #=> nil

Parameters:

  • string (String, #read)

    JSON string or IO-like object

  • options (Hash) (defaults to: {})

    parsing options (adapter-specific)

Returns:

  • (Object, nil)

    parsed Ruby object, or nil for blank input

Raises:

  • (ParseError)

    if parsing fails

  • (AdapterError)

    if the adapter doesn’t define a “ParseError“ constant



178
179
180
181
182
183
184
185
186
# File 'lib/multi_json.rb', line 178

def parse(string, options = {})
  adapter_class = current_adapter(options)
  parse_error_class = MultiJSON.parse_error_class_for(adapter_class)
  begin
    adapter_class.load(string, options)
  rescue parse_error_class => e
    raise ParseError.build(e, string)
  end
end

#use(new_adapter) ⇒ Class

Sets the adapter to use for JSON operations

The merged-options cache is only reset when the new adapter loads successfully. A failed “use(:nonexistent)“ leaves the cache in place so the previously-active adapter keeps its cached entries.

Examples:

MultiJSON.use(:oj)

Parameters:

  • new_adapter (Symbol, String, Module, nil)

    adapter specification

Returns:

  • (Class)

    the loaded adapter class



145
146
147
148
149
150
151
# File 'lib/multi_json.rb', line 145

def use(new_adapter)
  loaded = load_adapter(new_adapter)
  Concurrency.synchronize(:adapter) do
    OptionsCache.reset
    @adapter = loaded
  end
end