multi_json 1.20.1 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbba8097011550d30c5962bdd828a95b431ab54cc9a6d831844e78c78f2ddc74
4
- data.tar.gz: 767ba488de4f71c7503d69126130b88d904f656ec12cd2b0c039a1d66c39e594
3
+ metadata.gz: 6eb65ee97a46816e1bfe43fbeff173a83846bb1ff85e3c5e4fe97c80cec4dacf
4
+ data.tar.gz: 9eedd9bd17375a5540dc4878613a9165e49925d1997c24f4d9776f41efb1d7f0
5
5
  SHA512:
6
- metadata.gz: a0e46b45475da5fa524fdfc00c02b10bf9a3c677d3702bf81fa1bfaef278dc219a7720f082cc1a8edbc5fe07e2aa83e92a87ec2a7057a42edabd90a211fde34e
7
- data.tar.gz: 650953b9efc5ba89c84cb751c206972e8d95923c5b466558a97c340666a31b71645943e83b0186076cbf9a843da3dd306c3fdb654911873797bedf89e763e7d7
6
+ metadata.gz: c727bce3f895367c1092319c4725dedde9252706cc6da7a5d8b1ef4bef5abb025869b7a04dc44218dfe53198b8da0c0c36e1d61037824a34a59dcfd78a030f68
7
+ data.tar.gz: 2dc0b84560382d05f58549875227be1dbc32c274172f2c67e4c395f4baede84217061a10fcf22ebd078ce7e89fb25a88e067f7424b4bdd830c75081e96d2938f
data/README.md CHANGED
@@ -16,22 +16,33 @@ fastest available JSON coder. Here's how to use it:
16
16
  ```ruby
17
17
  require "multi_json"
18
18
 
19
- MultiJson.load('{"abc":"def"}') #=> {"abc" => "def"}
20
- MultiJson.load('{"abc":"def"}', symbolize_keys: true) #=> {abc: "def"}
21
- MultiJson.dump({abc: "def"}) # convert Ruby back to JSON
22
- MultiJson.dump({abc: "def"}, pretty: true) # encoded in a pretty form (if supported by the coder)
19
+ MultiJSON.parse('{"abc":"def"}') #=> {"abc" => "def"}
20
+ MultiJSON.parse('{"abc":"def"}', symbolize_names: true) #=> {abc: "def"}
21
+ MultiJSON.generate({abc: "def"}) # convert Ruby back to JSON
22
+ MultiJSON.generate({abc: "def"}, pretty: true) # encoded in a pretty form (if supported by the coder)
23
23
  ```
24
24
 
25
- `MultiJson.load` returns `nil` for `nil`, empty, and whitespace-only inputs
25
+ > [!IMPORTANT]
26
+ > **1.21.0 renames the public API to match Ruby stdlib `JSON`.** The canonical
27
+ > verbs are now `MultiJSON.parse` / `MultiJSON.generate`, and the canonical
28
+ > module is `MultiJSON` (all-caps). The legacy `MultiJson` constant,
29
+ > `MultiJSON.load` / `MultiJSON.dump`, `:symbolize_keys`, and friends still
30
+ > work but emit one-time deprecation warnings and **will be removed in 2.0.0**.
31
+ > Run your app with `ruby -W:deprecated` to surface them; the warnings are
32
+ > tagged with the `:deprecated` category so you can silence the whole set with
33
+ > `Warning[:deprecated] = false`. See [Deprecated in 1.21.0](#deprecated-in-1210)
34
+ > for the full list.
35
+
36
+ `MultiJSON.parse` returns `nil` for `nil`, empty, and whitespace-only inputs
26
37
  instead of raising, so a missing or blank payload is observable as a `nil`
27
- return value rather than an exception. When loading invalid JSON, MultiJSON
28
- will throw a `MultiJson::ParseError`. `MultiJson::DecodeError` and
29
- `MultiJson::LoadError` are aliases for backwards compatibility.
38
+ return value rather than an exception. When parsing invalid JSON, MultiJSON
39
+ will throw a `MultiJSON::ParseError`. `MultiJSON::DecodeError` and
40
+ `MultiJSON::LoadError` are aliases for backwards compatibility.
30
41
 
31
42
  ```ruby
32
43
  begin
33
- MultiJson.load("{invalid json}")
34
- rescue MultiJson::ParseError => exception
44
+ MultiJSON.parse("{invalid json}")
45
+ rescue MultiJSON::ParseError => exception
35
46
  exception.data #=> "{invalid json}"
36
47
  exception.cause #=> JSON::ParserError: ...
37
48
  exception.line #=> 1 (for adapters that report a location, e.g. Oj or the json gem)
@@ -39,6 +50,61 @@ rescue MultiJson::ParseError => exception
39
50
  end
40
51
  ```
41
52
 
53
+ ### Drop-in replacement for stdlib `JSON`
54
+
55
+ MultiJSON mirrors the surface of Ruby's stdlib [`JSON`][json-gem] so
56
+ most call sites swap in with a one-line change:
57
+
58
+ ```diff
59
+ - require "json"
60
+ + require "multi_json"
61
+
62
+ - JSON.parse(text, symbolize_names: true)
63
+ + MultiJSON.parse(text, symbolize_names: true)
64
+
65
+ - JSON.generate(object, pretty: true)
66
+ + MultiJSON.generate(object, pretty: true)
67
+ ```
68
+
69
+ Method names and the common options line up with stdlib so existing
70
+ pretty-print calls and option keys keep working without changes:
71
+
72
+ | stdlib `JSON` | `MultiJSON` | Status |
73
+ | ---------------------- | -------------------------- | :---: |
74
+ | `JSON.parse(str)` | `MultiJSON.parse(str)` | ✓ |
75
+ | `JSON.generate(obj)` | `MultiJSON.generate(obj)` | ✓ |
76
+ | `pretty: true` | `pretty: true` | ✓ |
77
+ | `symbolize_names: true` | `symbolize_names: true` | ✓ |
78
+
79
+ ### Deprecated in 1.21.0
80
+
81
+ The module constant and primary verbs were renamed to match Ruby
82
+ stdlib `JSON.parse` / `JSON.generate` and the JSON spec (RFC 8259).
83
+ The old names still work in 1.x but now emit a one-time deprecation
84
+ warning; **they will be removed in 2.0.0**.
85
+
86
+ | Deprecated | Use instead |
87
+ | ----------------------------- | ------------------------------- |
88
+ | `MultiJson` (constant) | `MultiJSON` (all-caps) |
89
+ | `MultiJSON.load(str)` | `MultiJSON.parse(str)` |
90
+ | `MultiJSON.dump(obj)` | `MultiJSON.generate(obj)` |
91
+ | `MultiJSON.load_options=` | `MultiJSON.parse_options=` |
92
+ | `MultiJSON.load_options` | `MultiJSON.parse_options` |
93
+ | `MultiJSON.dump_options=` | `MultiJSON.generate_options=` |
94
+ | `MultiJSON.dump_options` | `MultiJSON.generate_options` |
95
+ | `symbolize_keys:` option | `symbolize_names:` option |
96
+
97
+ The `MultiJson` constant (CamelCase) continues to work as a thin
98
+ delegator; every method call, constant lookup, and rescue clause
99
+ routes through `MultiJSON` transparently.
100
+
101
+ > [!TIP]
102
+ > The recommended upgrade path to 2.0 is: pin `~> 1.21` first, run
103
+ > `ruby -W:deprecated` against your app or test suite to surface every
104
+ > deprecation, migrate each call site to the canonical name, then bump to
105
+ > `~> 2.0`. The 2.0 release deletes the deprecated aliases entirely, so the
106
+ > warnings during 1.21.x are your map.
107
+
42
108
  `ParseError` instance has `cause` reader which contains the original exception.
43
109
  It also has `data` reader with the input that caused the problem, and `line`/`column`
44
110
  readers populated for adapters whose error messages include a location (Oj and the
@@ -46,13 +112,13 @@ json gem). Adapters that don't include one (Yajl, fast_jsonparser) leave both ni
46
112
 
47
113
  ### Tuning the options cache
48
114
 
49
- MultiJSON memoizes the merged option hash for each `load`/`dump` call so identical
50
- option hashes don't trigger repeated work. The cache is bounded — defaulting to 1000
51
- entries per direction — and applications that generate many distinct option hashes
52
- can raise the ceiling at runtime:
115
+ MultiJSON memoizes the merged option hash for each `parse`/`generate` call so
116
+ identical option hashes don't trigger repeated work. The cache is bounded —
117
+ defaulting to 1000 entries per direction — and applications that generate many
118
+ distinct option hashes can raise the ceiling at runtime:
53
119
 
54
120
  ```ruby
55
- MultiJson::OptionsCache.max_cache_size = 5000
121
+ MultiJSON::OptionsCache.max_cache_size = 5000
56
122
  ```
57
123
 
58
124
  `max_cache_size` must be a positive integer; `0`, negative values, and
@@ -60,14 +126,14 @@ non-integers raise `ArgumentError`.
60
126
 
61
127
  Lowering the limit only takes effect for *new* inserts; existing cache
62
128
  entries are left in place until normal eviction trims them below the
63
- new ceiling. Call `MultiJson::OptionsCache.reset` if you want to evict
129
+ new ceiling. Call `MultiJSON::OptionsCache.reset` if you want to evict
64
130
  immediately.
65
131
 
66
132
  The `use` method, which sets the MultiJSON adapter, takes either a symbol or a
67
133
  class (to allow for custom JSON parsers) that responds to both `.load` and `.dump`
68
134
  at the class level.
69
135
 
70
- When MultiJSON fails to load the specified adapter, it'll throw `MultiJson::AdapterError`
136
+ When MultiJSON fails to load the specified adapter, it'll throw `MultiJSON::AdapterError`
71
137
  which inherits from `ArgumentError`.
72
138
 
73
139
  ### Writing a custom adapter
@@ -88,38 +154,49 @@ class MyAdapter
88
154
  end
89
155
  end
90
156
 
91
- MultiJson.use(MyAdapter)
157
+ MultiJSON.use(MyAdapter)
92
158
  ```
93
159
 
94
- `ParseError` is required: `MultiJson.load` rescues `MyAdapter::ParseError`
95
- to wrap parse failures in `MultiJson::ParseError`, and an adapter that
96
- omits the constant raises `MultiJson::AdapterError` on the first parse
160
+ `ParseError` is required: `MultiJSON.parse` rescues `MyAdapter::ParseError`
161
+ to wrap parse failures in `MultiJSON::ParseError`, and an adapter that
162
+ omits the constant raises `MultiJSON::AdapterError` on the first parse
97
163
  attempt instead of producing a confusing `NameError`.
98
164
 
99
- For more, inherit from `MultiJson::Adapter` to pick up shared option
165
+ For more, inherit from `MultiJSON::Adapter` to pick up shared option
100
166
  merging, the `defaults :load, ...` / `defaults :dump, ...` DSL, and the
101
167
  blank-input short-circuit. The built-in adapters in
102
168
  `lib/multi_json/adapters/` are working examples.
103
169
 
170
+ > [!NOTE]
171
+ > The adapter contract methods on the adapter class itself stay named
172
+ > `.load` / `.dump` in 1.21.x (and the `defaults :load, ...` / `defaults
173
+ > :dump, ...` DSL keys match). The 2.0 release renames them to `.parse` /
174
+ > `.generate` to align with the public API; if you ship a custom adapter,
175
+ > you'll need to rename those methods (and the `defaults` keys) when you
176
+ > upgrade.
177
+
104
178
  MultiJSON tries to have intelligent defaulting. If any supported library is
105
179
  already loaded, MultiJSON uses it before attempting to load others. When no
106
180
  backend is preloaded, MultiJSON walks its preference list and uses the first
107
- one that loads successfully:
108
-
109
- 1. `fast_jsonparser`
110
- 2. `oj`
111
- 3. `yajl-ruby`
112
- 4. `jrjackson`
113
- 5. The JSON gem
114
- 6. `gson`
115
-
116
- This order is a best-effort historical ranking by typical parse/dump
117
- throughput on representative workloads, not a guaranteed benchmark. Real-world
118
- performance depends on the document shape, the Ruby implementation, and
119
- whether you're calling `load` or `dump`. The JSON gem is a Ruby default gem,
120
- so it's always available as a last-resort fallback on any supported Ruby. If
121
- you have a workload where a different backend is faster, set it explicitly
122
- with `MultiJson.use(:your_adapter)`.
181
+ one that loads successfully. The list is split per platform — JRuby's
182
+ available adapter set differs from MRI's, and the bundled benchmark suite
183
+ ranks `json_gem` ahead of `fast_jsonparser`/`oj`/`yajl` on Ruby 3.4+. CI
184
+ re-runs the benchmark and fails if the observed ranking diverges from the
185
+ table below.
186
+
187
+ | rank | MRI / TruffleRuby | JRuby |
188
+ | ---- | ----------------- | --------------- |
189
+ | 1 | The JSON gem | `jrjackson` |
190
+ | 2 | `fast_jsonparser` | The JSON gem |
191
+ | 3 | `oj` | `gson` |
192
+ | 4 | `yajl-ruby` | — |
193
+
194
+ A dash means the adapter isn't usable on that runtime: `fast_jsonparser`,
195
+ `oj`, and `yajl-ruby` are MRI/TruffleRuby C extensions with no JRuby builds;
196
+ `jrjackson` and `gson` are JRuby-only. The JSON gem is a Ruby default gem,
197
+ so it's always available as a last-resort fallback on any supported Ruby.
198
+ If you have a workload where a different backend is faster, set it
199
+ explicitly with `MultiJSON.use(:your_adapter)`.
123
200
 
124
201
  ## Gem Variants
125
202
 
@@ -3,7 +3,7 @@
3
3
  require "singleton"
4
4
  require_relative "options"
5
5
 
6
- module MultiJson
6
+ module MultiJSON
7
7
  # Base class for JSON adapter implementations
8
8
  #
9
9
  # Each adapter wraps a specific JSON library (Oj, JSON gem, etc.) and
@@ -24,7 +24,7 @@ module MultiJson
24
24
  VALID_DEFAULTS_ACTIONS = %i[load dump].freeze
25
25
  private_constant :BLANK_PATTERN, :VALID_DEFAULTS_ACTIONS
26
26
 
27
- # Get default load options, walking the superclass chain
27
+ # Get default parse options, walking the superclass chain
28
28
  #
29
29
  # Returns the closest ancestor's `@default_load_options` ivar so a
30
30
  # parent class calling {.defaults} after a subclass has been
@@ -33,18 +33,36 @@ module MultiJson
33
33
  #
34
34
  # @api private
35
35
  # @return [Hash] frozen options hash
36
- def default_load_options
36
+ def default_parse_options
37
37
  walk_default_options(:@default_load_options)
38
38
  end
39
39
 
40
- # Get default dump options, walking the superclass chain
40
+ # Get default generate options, walking the superclass chain
41
41
  #
42
42
  # @api private
43
43
  # @return [Hash] frozen options hash
44
- def default_dump_options
44
+ def default_generate_options
45
45
  walk_default_options(:@default_dump_options)
46
46
  end
47
47
 
48
+ # Get default parse options, walking the superclass chain
49
+ #
50
+ # @api private
51
+ # @deprecated Use {.default_parse_options} instead. Will be removed in v2.0.
52
+ # @return [Hash] frozen options hash
53
+ def default_load_options
54
+ default_parse_options
55
+ end
56
+
57
+ # Get default generate options, walking the superclass chain
58
+ #
59
+ # @api private
60
+ # @deprecated Use {.default_generate_options} instead. Will be removed in v2.0.
61
+ # @return [Hash] frozen options hash
62
+ def default_dump_options
63
+ default_generate_options
64
+ end
65
+
48
66
  # DSL for setting adapter-specific default options
49
67
  #
50
68
  # ``action`` must be ``:load`` or ``:dump``; ``value`` must be a
@@ -59,7 +77,7 @@ module MultiJson
59
77
  # @raise [ArgumentError] when action is anything other than :load
60
78
  # or :dump, or when value isn't a Hash
61
79
  # @example Set load defaults for an adapter
62
- # class MyAdapter < MultiJson::Adapter
80
+ # class MyAdapter < MultiJSON::Adapter
63
81
  # defaults :load, symbolize_keys: false
64
82
  # end
65
83
  def defaults(action, value)
@@ -139,7 +157,7 @@ module MultiJson
139
157
  BLANK_PATTERN.match?(input.valid_encoding? ? input : input.scrub)
140
158
  end
141
159
 
142
- # Merges dump options from adapter, global, and call-site
160
+ # Merges generate options from adapter, global, and call-site
143
161
  #
144
162
  # @api private
145
163
  # @param options [Hash] call-site options
@@ -147,11 +165,18 @@ module MultiJson
147
165
  def merged_dump_options(options)
148
166
  cache_key = strip_adapter_key(options)
149
167
  OptionsCache.dump.fetch(cache_key) do
150
- dump_options(cache_key).merge(MultiJson.dump_options(cache_key)).merge!(cache_key)
168
+ generate_options(cache_key).merge(MultiJSON.generate_options(cache_key)).merge!(cache_key)
151
169
  end
152
170
  end
153
171
 
154
- # Merges load options from adapter, global, and call-site
172
+ # Merges parse options from adapter, global, and call-site
173
+ #
174
+ # Each layer is normalized first so a deprecated ``:symbolize_keys``
175
+ # key in any source becomes the canonical ``:symbolize_names`` —
176
+ # done per-layer rather than post-merge so the expected override
177
+ # semantics (call-site > global > adapter default) still apply
178
+ # when a caller mixes the deprecated and canonical names across
179
+ # layers.
155
180
  #
156
181
  # @api private
157
182
  # @param options [Hash] call-site options
@@ -159,10 +184,37 @@ module MultiJson
159
184
  def merged_load_options(options)
160
185
  cache_key = strip_adapter_key(options)
161
186
  OptionsCache.load.fetch(cache_key) do
162
- load_options(cache_key).merge(MultiJson.load_options(cache_key)).merge!(cache_key)
187
+ adapter = normalize_symbolize_option(parse_options(cache_key))
188
+ global = normalize_symbolize_option(MultiJSON.parse_options(cache_key))
189
+ call_site = normalize_symbolize_option(cache_key)
190
+ adapter.merge(global).merge!(call_site)
163
191
  end
164
192
  end
165
193
 
194
+ # Translate the deprecated ``:symbolize_keys`` option to ``:symbolize_names``
195
+ #
196
+ # Matches Ruby stdlib's ``JSON.parse`` naming. Emits a one-time
197
+ # deprecation warning on first encounter of ``:symbolize_keys``.
198
+ # When both names appear in the same layer (unusual — only
199
+ # possible if the caller explicitly set both), the canonical
200
+ # ``:symbolize_names`` value wins and ``:symbolize_keys`` is
201
+ # silently dropped.
202
+ #
203
+ # @api private
204
+ # @param options [Hash] options layer to normalize
205
+ # @return [Hash] hash with ``:symbolize_keys`` translated, or the
206
+ # original hash when no translation is needed
207
+ def normalize_symbolize_option(options)
208
+ return options unless options.key?(:symbolize_keys)
209
+
210
+ MultiJSON.warn_deprecation_once(:symbolize_keys_option,
211
+ "The :symbolize_keys option is deprecated and will be removed in v2.0. Use :symbolize_names instead.")
212
+
213
+ new_opts = options.except(:symbolize_keys)
214
+ new_opts[:symbolize_names] = options[:symbolize_keys] unless new_opts.key?(:symbolize_names)
215
+ new_opts
216
+ end
217
+
166
218
  # Removes the :adapter key from options for cache key
167
219
  #
168
220
  # Returns a shared frozen empty hash for the common no-options call
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module MultiJson
3
+ module MultiJSON
4
4
  # Raised when an adapter cannot be loaded or is not recognized
5
5
  #
6
6
  # @api public
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module MultiJson
3
+ module MultiJSON
4
4
  # Handles adapter discovery, loading, and selection
5
5
  #
6
6
  # Adapters can be specified as:
@@ -17,14 +17,34 @@ module MultiJson
17
17
  # constant whose presence indicates the backing library is already
18
18
  # loaded. ``loaded`` is a ``::``-separated path so we can walk it
19
19
  # without an explicit ``defined?`` check.
20
- ADAPTERS = {
21
- fast_jsonparser: {require: "fast_jsonparser", loaded: "FastJsonparser"},
22
- oj: {require: "oj", loaded: "Oj"},
23
- yajl: {require: "yajl", loaded: "Yajl"},
24
- jr_jackson: {require: "jrjackson", loaded: "JrJackson"},
25
- json_gem: {require: "json", loaded: "JSON::Ext::Parser"},
26
- gson: {require: "gson", loaded: "Gson"}
27
- }.freeze
20
+ #
21
+ # The hash order is split per platform: on MRI/TruffleRuby the
22
+ # bundled benchmark suite ranks json_gem ahead of fast_jsonparser/
23
+ # oj/yajl on Ruby 3.4+; on JRuby the FFI-vs-pure-Ruby tradeoff
24
+ # hasn't been re-benchmarked yet, so jr_jackson stays first there.
25
+ # CI re-runs the benchmark with ``--verify-preference`` to fail
26
+ # if the observed ranking diverges.
27
+ # :nocov:
28
+ ADAPTERS = if RUBY_ENGINE == "jruby"
29
+ {
30
+ jr_jackson: {require: "jrjackson", loaded: "JrJackson"},
31
+ json_gem: {require: "json", loaded: "JSON::Ext::Parser"},
32
+ gson: {require: "gson", loaded: "Gson"},
33
+ fast_jsonparser: {require: "fast_jsonparser", loaded: "FastJsonparser"},
34
+ oj: {require: "oj", loaded: "Oj"},
35
+ yajl: {require: "yajl", loaded: "Yajl"}
36
+ }.freeze
37
+ else
38
+ {
39
+ json_gem: {require: "json", loaded: "JSON::Ext::Parser"},
40
+ fast_jsonparser: {require: "fast_jsonparser", loaded: "FastJsonparser"},
41
+ oj: {require: "oj", loaded: "Oj"},
42
+ yajl: {require: "yajl", loaded: "Yajl"},
43
+ jr_jackson: {require: "jrjackson", loaded: "JrJackson"},
44
+ gson: {require: "gson", loaded: "Gson"}
45
+ }.freeze
46
+ end
47
+ # :nocov:
28
48
  private_constant :ADAPTERS
29
49
 
30
50
  # Backwards-compatible view of {ADAPTERS} that exposes only the
@@ -46,13 +66,13 @@ module MultiJson
46
66
  #
47
67
  # Used by adapters that only implement one direction (e.g.
48
68
  # FastJsonparser only parses) so the other direction can be delegated
49
- # to whichever library MultiJson would otherwise pick.
69
+ # to whichever library MultiJSON would otherwise pick.
50
70
  #
51
71
  # @api private
52
72
  # @param excluded [Symbol] adapter name to skip during detection
53
73
  # @return [Class] the adapter class
54
74
  # @example
55
- # AdapterSelector.default_adapter_excluding(:fast_jsonparser) #=> MultiJson::Adapters::Oj
75
+ # AdapterSelector.default_adapter_excluding(:fast_jsonparser) #=> MultiJSON::Adapters::Oj
56
76
  def default_adapter_excluding(excluded)
57
77
  Concurrency.synchronize(:default_adapter) do
58
78
  name = loaded_adapter(excluding: excluded)
@@ -131,7 +151,7 @@ module MultiJson
131
151
  # @return [void]
132
152
  def warn_about_fallback
133
153
  Kernel.warn(
134
- "[WARNING] MultiJson is falling back to the json_gem adapter " \
154
+ "[WARNING] MultiJSON is falling back to the json_gem adapter " \
135
155
  "because no other JSON library could be loaded."
136
156
  )
137
157
  end
@@ -169,7 +189,7 @@ module MultiJson
169
189
  require_relative "adapters/#{normalized}"
170
190
 
171
191
  class_name = normalized.split("_").map(&:capitalize).join
172
- ::MultiJson::Adapters.const_get(class_name)
192
+ ::MultiJSON::Adapters.const_get(class_name)
173
193
  end
174
194
 
175
195
  # Validate that an adapter satisfies the documented contract
@@ -187,7 +207,7 @@ module MultiJson
187
207
  raise AdapterError, "Adapter #{adapter} must respond to .load" unless adapter.respond_to?(:load)
188
208
  raise AdapterError, "Adapter #{adapter} must respond to .dump" unless adapter.respond_to?(:dump)
189
209
 
190
- MultiJson.parse_error_class_for(adapter)
210
+ MultiJSON.parse_error_class_for(adapter)
191
211
  adapter
192
212
  end
193
213
  end
@@ -4,13 +4,13 @@ require "fast_jsonparser"
4
4
  require_relative "../adapter"
5
5
  require_relative "../adapter_selector"
6
6
 
7
- module MultiJson
7
+ module MultiJSON
8
8
  module Adapters
9
9
  # Use the FastJsonparser library to load, and the fastest other
10
10
  # available adapter to dump.
11
11
  #
12
12
  # FastJsonparser only implements parsing, so the ``dump`` side of
13
- # the adapter is delegated to whichever adapter MultiJson would
13
+ # the adapter is delegated to whichever adapter MultiJSON would
14
14
  # pick if FastJsonparser weren't installed (oj → yajl → jr_jackson
15
15
  # → json_gem → gson). The delegate is resolved lazily at the first
16
16
  # ``dump`` call, not at file load time, so load order doesn't lock
@@ -18,7 +18,7 @@ module MultiJson
18
18
  # the first ``dump`` call (typical applications already have ``oj``
19
19
  # loaded by then).
20
20
  class FastJsonparser < Adapter
21
- defaults :load, symbolize_keys: false
21
+ defaults :load, symbolize_names: false
22
22
 
23
23
  # Exception raised when JSON parsing fails
24
24
  ParseError = ::FastJsonparser::ParseError
@@ -43,8 +43,8 @@ module MultiJson
43
43
  # @api private
44
44
  # @return [Class] delegate adapter class
45
45
  def dump_delegate
46
- MultiJson::Concurrency.synchronize(:dump_delegate) do
47
- @dump_delegate ||= MultiJson::AdapterSelector.default_adapter_excluding(:fast_jsonparser)
46
+ MultiJSON::Concurrency.synchronize(:dump_delegate) do
47
+ @dump_delegate ||= MultiJSON::AdapterSelector.default_adapter_excluding(:fast_jsonparser)
48
48
  end
49
49
  end
50
50
  end
@@ -53,19 +53,21 @@ module MultiJson
53
53
  #
54
54
  # FastJsonparser.parse only accepts ``symbolize_keys`` and raises
55
55
  # on unknown keyword arguments, so the adapter explicitly forwards
56
- # only that option and silently drops the rest. Pass other options
57
- # through ``MultiJson.load_options=`` and they'll apply to whichever
58
- # adapter MultiJson selects when fast_jsonparser isn't installed.
56
+ # MultiJSON's canonical ``:symbolize_names`` option as
57
+ # FastJsonparser's native ``symbolize_keys:`` kwarg and silently
58
+ # drops the rest. Pass other options through
59
+ # ``MultiJSON.parse_options=`` and they'll apply to whichever
60
+ # adapter MultiJSON selects when fast_jsonparser isn't installed.
59
61
  #
60
62
  # @api private
61
63
  # @param string [String] JSON string to parse
62
- # @param options [Hash] parsing options (only :symbolize_keys is honored)
64
+ # @param options [Hash] parsing options (only :symbolize_names is honored)
63
65
  # @return [Object] parsed Ruby object
64
66
  #
65
67
  # @example Parse JSON string
66
68
  # adapter.load('{"key":"value"}') #=> {"key" => "value"}
67
69
  def load(string, options = {})
68
- ::FastJsonparser.parse(string, symbolize_keys: options[:symbolize_keys])
70
+ ::FastJsonparser.parse(string, symbolize_keys: options[:symbolize_names])
69
71
  end
70
72
  end
71
73
  end
@@ -3,7 +3,7 @@
3
3
  require_relative "../adapter"
4
4
  require "json"
5
5
 
6
- module MultiJson
6
+ module MultiJSON
7
7
  module Adapters
8
8
  # Use the JSON gem to dump/load.
9
9
  class JsonGem < Adapter
@@ -44,7 +44,7 @@ module MultiJson
44
44
  raise ::JSON::ParserError, "Invalid UTF-8 byte sequence in JSON input" unless string.valid_encoding?
45
45
  end
46
46
 
47
- ::JSON.parse(string, translate_load_options(options))
47
+ ::JSON.parse(string, options)
48
48
  end
49
49
 
50
50
  # Serialize a Ruby object to JSON
@@ -67,23 +67,6 @@ module MultiJson
67
67
 
68
68
  ::JSON.pretty_generate(json_object, PRETTY_STATE_PROTOTYPE.merge(options.except(:pretty)))
69
69
  end
70
-
71
- private
72
-
73
- # Translate ``:symbolize_keys`` into JSON gem's ``:symbolize_names``
74
- #
75
- # Returns a new hash without mutating the input. ``options`` is the
76
- # cached hash returned from {Adapter.merged_load_options}, so in-place
77
- # edits would pollute the cache and corrupt subsequent calls.
78
- #
79
- # @api private
80
- # @param options [Hash] merged load options
81
- # @return [Hash] options with ``:symbolize_keys`` translated
82
- def translate_load_options(options)
83
- return options unless options[:symbolize_keys]
84
-
85
- options.except(:symbolize_keys).merge(symbolize_names: true)
86
- end
87
70
  end
88
71
  end
89
72
  end
@@ -4,7 +4,7 @@ require "oj"
4
4
  require_relative "../adapter"
5
5
  require_relative "oj_common"
6
6
 
7
- module MultiJson
7
+ module MultiJSON
8
8
  # Namespace for JSON adapter implementations
9
9
  #
10
10
  # Each adapter wraps a specific JSON library and provides a consistent
@@ -14,7 +14,7 @@ module MultiJson
14
14
  class Oj < Adapter
15
15
  include OjCommon
16
16
 
17
- defaults :load, mode: :strict, symbolize_keys: false
17
+ defaults :load, mode: :strict, symbolize_names: false
18
18
  defaults :dump, mode: :compat, time_format: :ruby, use_to_json: true
19
19
 
20
20
  # In certain cases the Oj gem may throw a ``JSON::ParserError``
@@ -69,10 +69,10 @@ module MultiJson
69
69
 
70
70
  private
71
71
 
72
- # Translate ``:symbolize_keys`` into Oj's ``:symbol_keys``
72
+ # Translate ``:symbolize_names`` into Oj's ``:symbol_keys``
73
73
  #
74
74
  # Returns a new hash without mutating the input.
75
- # ``:symbol_keys`` is always set (true or false) so MultiJson's
75
+ # ``:symbol_keys`` is always set (true or false) so MultiJSON's
76
76
  # behavior is independent of any global ``Oj.default_options``
77
77
  # the host application may have set. The input is the cached hash
78
78
  # returned from {Adapter.merged_load_options}, so in-place edits
@@ -80,9 +80,9 @@ module MultiJson
80
80
  #
81
81
  # @api private
82
82
  # @param options [Hash] merged load options
83
- # @return [Hash] options with ``:symbolize_keys`` translated
83
+ # @return [Hash] options with ``:symbolize_names`` translated
84
84
  def translate_load_options(options)
85
- options.except(:symbolize_keys).merge(symbol_keys: options[:symbolize_keys] == true)
85
+ options.except(:symbolize_names).merge(symbol_keys: options[:symbolize_names] == true)
86
86
  end
87
87
  end
88
88
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module MultiJson
3
+ module MultiJSON
4
4
  module Adapters
5
5
  # Shared functionality for the Oj adapter
6
6
  #
@@ -3,7 +3,7 @@
3
3
  require "yajl"
4
4
  require_relative "../adapter"
5
5
 
6
- module MultiJson
6
+ module MultiJSON
7
7
  module Adapters
8
8
  # Use the Yajl-Ruby library to dump/load.
9
9
  class Yajl < Adapter