multi_json 1.20.1-java → 1.21.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +115 -38
- data/lib/multi_json/adapter.rb +62 -10
- data/lib/multi_json/adapter_error.rb +1 -1
- data/lib/multi_json/adapter_selector.rb +34 -14
- data/lib/multi_json/adapters/fast_jsonparser.rb +12 -10
- data/lib/multi_json/adapters/gson.rb +21 -4
- data/lib/multi_json/adapters/jr_jackson.rb +19 -2
- data/lib/multi_json/adapters/json_gem.rb +2 -19
- data/lib/multi_json/adapters/oj.rb +6 -6
- data/lib/multi_json/adapters/oj_common.rb +1 -1
- data/lib/multi_json/adapters/yajl.rb +1 -1
- data/lib/multi_json/concurrency.rb +7 -7
- data/lib/multi_json/deprecated.rb +26 -23
- data/lib/multi_json/options.rb +97 -23
- data/lib/multi_json/options_cache/concurrent_store.rb +1 -1
- data/lib/multi_json/options_cache.rb +7 -7
- data/lib/multi_json/parse_error.rb +1 -1
- data/lib/multi_json/version.rb +6 -6
- data/lib/multi_json.rb +123 -53
- metadata +5 -7
- data/CHANGELOG.md +0 -312
- data/CONTRIBUTING.md +0 -53
data/lib/multi_json.rb
CHANGED
|
@@ -10,7 +10,7 @@ require_relative "multi_json/adapter_selector"
|
|
|
10
10
|
|
|
11
11
|
# A unified interface for JSON libraries in Ruby
|
|
12
12
|
#
|
|
13
|
-
#
|
|
13
|
+
# MultiJSON allows swapping between JSON backends without changing your code.
|
|
14
14
|
# It auto-detects available JSON libraries and uses the fastest one available.
|
|
15
15
|
#
|
|
16
16
|
# ## Method-definition patterns
|
|
@@ -19,9 +19,9 @@ require_relative "multi_json/adapter_selector"
|
|
|
19
19
|
#
|
|
20
20
|
# 1. ``module_function`` creates both a class method and a private instance
|
|
21
21
|
# method from a single ``def``. This is used for the hot-path API
|
|
22
|
-
# (``adapter``, ``use``, ``adapter=``, ``
|
|
23
|
-
# ``current_adapter``) so that both ``
|
|
24
|
-
# ``Class.new { include
|
|
22
|
+
# (``adapter``, ``use``, ``adapter=``, ``parse``, ``generate``,
|
|
23
|
+
# ``current_adapter``) so that both ``MultiJSON.parse(...)`` and legacy
|
|
24
|
+
# ``Class.new { include MultiJSON }.new.send(:parse, ...)`` invocations
|
|
25
25
|
# work through the same body. The instance versions are re-publicized
|
|
26
26
|
# below so YARD renders them as part of the public API.
|
|
27
27
|
# 2. ``def self.foo`` creates only a singleton method, giving mutation
|
|
@@ -29,20 +29,20 @@ require_relative "multi_json/adapter_selector"
|
|
|
29
29
|
# {.with_adapter}, which needs precise mutation coverage of its
|
|
30
30
|
# fiber-local save/restore logic.
|
|
31
31
|
#
|
|
32
|
-
# Deprecated public API (``decode``, ``encode``, ``engine``,
|
|
33
|
-
# {file:lib/multi_json/deprecated.rb} so this
|
|
34
|
-
# current surface.
|
|
32
|
+
# Deprecated public API (``decode``, ``encode``, ``engine``, ``load``,
|
|
33
|
+
# ``dump``, etc.) lives in {file:lib/multi_json/deprecated.rb} so this
|
|
34
|
+
# file stays focused on the current surface.
|
|
35
35
|
#
|
|
36
36
|
# @example Basic usage
|
|
37
|
-
#
|
|
38
|
-
#
|
|
37
|
+
# MultiJSON.parse('{"foo":"bar"}') #=> {"foo" => "bar"}
|
|
38
|
+
# MultiJSON.generate({foo: "bar"}) #=> '{"foo":"bar"}'
|
|
39
39
|
#
|
|
40
40
|
# @example Specifying an adapter
|
|
41
|
-
#
|
|
42
|
-
#
|
|
41
|
+
# MultiJSON.use(:oj)
|
|
42
|
+
# MultiJSON.parse('{"foo":"bar"}', adapter: :json_gem)
|
|
43
43
|
#
|
|
44
44
|
# @api public
|
|
45
|
-
module
|
|
45
|
+
module MultiJSON
|
|
46
46
|
extend Options
|
|
47
47
|
extend AdapterSelector
|
|
48
48
|
|
|
@@ -52,37 +52,38 @@ module MultiJson
|
|
|
52
52
|
DEPRECATION_WARNINGS_SHOWN = Set.new
|
|
53
53
|
private_constant :DEPRECATION_WARNINGS_SHOWN
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
# Emit a deprecation warning at most once per process for the given key
|
|
56
|
+
#
|
|
57
|
+
# Defined as a singleton method (rather than via module_function) so
|
|
58
|
+
# there is exactly one definition for mutation tests to target.
|
|
59
|
+
# Public so the deprecated ``load_options`` / ``dump_options``
|
|
60
|
+
# aliases on the {Options} mixin can invoke it without routing
|
|
61
|
+
# through ``MultiJSON.send(...)``.
|
|
62
|
+
#
|
|
63
|
+
# The warning is tagged with the ``:deprecated`` category so callers
|
|
64
|
+
# can silence the whole set with ``Warning[:deprecated] = false`` or
|
|
65
|
+
# surface it via ``ruby -W:deprecated`` — the standard Ruby idiom for
|
|
66
|
+
# library deprecations since 2.7.
|
|
67
|
+
#
|
|
68
|
+
# @api private
|
|
69
|
+
# @param key [Symbol] identifier for the deprecation (typically the method name)
|
|
70
|
+
# @param message [String] warning message to emit on first call
|
|
71
|
+
# @return [void]
|
|
72
|
+
# @example
|
|
73
|
+
# MultiJSON.warn_deprecation_once(:foo, "MultiJSON.foo is deprecated")
|
|
74
|
+
def self.warn_deprecation_once(key, message)
|
|
75
|
+
Concurrency.synchronize(:deprecation_warnings) do
|
|
76
|
+
return if DEPRECATION_WARNINGS_SHOWN.include?(key)
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
78
|
+
Kernel.warn(message, category: :deprecated)
|
|
79
|
+
DEPRECATION_WARNINGS_SHOWN.add(key)
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
# Resolve the ``ParseError`` constant for an adapter class
|
|
83
84
|
#
|
|
84
85
|
# The result is memoized on the adapter class itself in a
|
|
85
|
-
# ``@_multi_json_parse_error`` ivar so subsequent ``
|
|
86
|
+
# ``@_multi_json_parse_error`` ivar so subsequent ``MultiJSON.load``
|
|
86
87
|
# calls skip the constant lookup entirely. The lookup is performed
|
|
87
88
|
# with ``inherit: false`` so a stray top-level ``::ParseError``
|
|
88
89
|
# constant in the host process is correctly ignored on every
|
|
@@ -122,7 +123,7 @@ module MultiJson
|
|
|
122
123
|
# @api public
|
|
123
124
|
# @return [Class] the current adapter class
|
|
124
125
|
# @example
|
|
125
|
-
#
|
|
126
|
+
# MultiJSON.adapter #=> MultiJSON::Adapters::Oj
|
|
126
127
|
def adapter
|
|
127
128
|
override = Fiber[:multi_json_adapter]
|
|
128
129
|
return override if override
|
|
@@ -140,7 +141,7 @@ module MultiJson
|
|
|
140
141
|
# @param new_adapter [Symbol, String, Module, nil] adapter specification
|
|
141
142
|
# @return [Class] the loaded adapter class
|
|
142
143
|
# @example
|
|
143
|
-
#
|
|
144
|
+
# MultiJSON.use(:oj)
|
|
144
145
|
def use(new_adapter)
|
|
145
146
|
loaded = load_adapter(new_adapter)
|
|
146
147
|
Concurrency.synchronize(:adapter) do
|
|
@@ -154,7 +155,7 @@ module MultiJson
|
|
|
154
155
|
# @api public
|
|
155
156
|
# @return [Class] the loaded adapter class
|
|
156
157
|
# @example
|
|
157
|
-
#
|
|
158
|
+
# MultiJSON.adapter = :json_gem
|
|
158
159
|
alias_method :adapter=, :use
|
|
159
160
|
module_function :adapter=
|
|
160
161
|
|
|
@@ -171,12 +172,12 @@ module MultiJson
|
|
|
171
172
|
# @raise [ParseError] if parsing fails
|
|
172
173
|
# @raise [AdapterError] if the adapter doesn't define a ``ParseError`` constant
|
|
173
174
|
# @example
|
|
174
|
-
#
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
def
|
|
175
|
+
# MultiJSON.parse('{"foo":"bar"}') #=> {"foo" => "bar"}
|
|
176
|
+
# MultiJSON.parse("") #=> nil
|
|
177
|
+
# MultiJSON.parse(" \n") #=> nil
|
|
178
|
+
def parse(string, options = {})
|
|
178
179
|
adapter_class = current_adapter(options)
|
|
179
|
-
parse_error_class =
|
|
180
|
+
parse_error_class = MultiJSON.parse_error_class_for(adapter_class)
|
|
180
181
|
begin
|
|
181
182
|
adapter_class.load(string, options)
|
|
182
183
|
rescue parse_error_class => e
|
|
@@ -195,7 +196,7 @@ module MultiJson
|
|
|
195
196
|
# nil to use the process default
|
|
196
197
|
# @return [Class] adapter class
|
|
197
198
|
# @example
|
|
198
|
-
#
|
|
199
|
+
# MultiJSON.current_adapter(adapter: :oj) #=> MultiJSON::Adapters::Oj
|
|
199
200
|
def current_adapter(options = {})
|
|
200
201
|
options ||= Options::EMPTY_OPTIONS
|
|
201
202
|
adapter_override = options[:adapter]
|
|
@@ -209,15 +210,15 @@ module MultiJson
|
|
|
209
210
|
# @param options [Hash] serialization options (adapter-specific)
|
|
210
211
|
# @return [String] JSON string
|
|
211
212
|
# @example
|
|
212
|
-
#
|
|
213
|
-
def
|
|
213
|
+
# MultiJSON.generate({foo: "bar"}) #=> '{"foo":"bar"}'
|
|
214
|
+
def generate(object, options = {})
|
|
214
215
|
current_adapter(options).dump(object, options)
|
|
215
216
|
end
|
|
216
217
|
|
|
217
218
|
# Re-publicize the instance versions of the module_function methods so
|
|
218
219
|
# YARD/yardstick render them as part of the public API and legacy
|
|
219
|
-
# ``include
|
|
220
|
-
public :adapter, :use, :adapter=, :
|
|
220
|
+
# ``include MultiJSON`` consumers can call them without ``.send``.
|
|
221
|
+
public :adapter, :use, :adapter=, :parse, :current_adapter, :generate
|
|
221
222
|
|
|
222
223
|
# ===========================================================================
|
|
223
224
|
# Public API (def self.foo: singleton-only, for mutation-test precision)
|
|
@@ -236,7 +237,7 @@ module MultiJson
|
|
|
236
237
|
# @yield block to execute with the temporary adapter
|
|
237
238
|
# @return [Object] result of the block
|
|
238
239
|
# @example
|
|
239
|
-
#
|
|
240
|
+
# MultiJSON.with_adapter(:json_gem) { MultiJSON.dump({}) }
|
|
240
241
|
def self.with_adapter(new_adapter)
|
|
241
242
|
previous_override = Fiber[:multi_json_adapter]
|
|
242
243
|
Fiber[:multi_json_adapter] = load_adapter(new_adapter)
|
|
@@ -251,18 +252,87 @@ module MultiJson
|
|
|
251
252
|
|
|
252
253
|
private
|
|
253
254
|
|
|
254
|
-
# Instance-method delegate for {
|
|
255
|
+
# Instance-method delegate for {MultiJSON.with_adapter}
|
|
255
256
|
#
|
|
256
257
|
# @api private
|
|
257
258
|
# @param new_adapter [Symbol, String, Module] adapter to use
|
|
258
259
|
# @yield block to execute with the temporary adapter
|
|
259
260
|
# @return [Object] result of the block
|
|
260
261
|
# @example
|
|
261
|
-
# class Foo; include
|
|
262
|
+
# class Foo; include MultiJSON; end
|
|
262
263
|
# Foo.new.send(:with_adapter, :json_gem) { ... }
|
|
263
264
|
def with_adapter(new_adapter, &)
|
|
264
|
-
|
|
265
|
+
MultiJSON.with_adapter(new_adapter, &)
|
|
265
266
|
end
|
|
266
267
|
end
|
|
267
268
|
|
|
268
269
|
require_relative "multi_json/deprecated"
|
|
270
|
+
|
|
271
|
+
# Backward-compatible alias for the legacy ``MultiJson`` constant name
|
|
272
|
+
#
|
|
273
|
+
# Downstream code that still writes ``MultiJson.parse(...)`` or
|
|
274
|
+
# ``rescue MultiJson::ParseError`` continues to work, but emits a
|
|
275
|
+
# one-time deprecation warning pointing at ``MultiJSON``. The module
|
|
276
|
+
# forwards every method call to {MultiJSON} via {.method_missing} and
|
|
277
|
+
# resolves constant access via {.const_missing}, so both dotted calls
|
|
278
|
+
# and ``::`` constant lookups (including rescue clauses) route through
|
|
279
|
+
# the canonical module.
|
|
280
|
+
#
|
|
281
|
+
# @api public
|
|
282
|
+
# @deprecated Use {MultiJSON} (all-caps) instead. Will be removed in v2.0.
|
|
283
|
+
module MultiJson
|
|
284
|
+
class << self
|
|
285
|
+
# Forward method calls to {MultiJSON}, emitting a one-time warning
|
|
286
|
+
#
|
|
287
|
+
# Uses explicit ``*args, **kwargs, &block`` forwarding because
|
|
288
|
+
# mutant's AST structure table on the current parser version does
|
|
289
|
+
# not yet recognize ``...`` forwarding nodes, so the module would
|
|
290
|
+
# crash mutation analysis. The rubocop exclusions below document
|
|
291
|
+
# that intent.
|
|
292
|
+
#
|
|
293
|
+
# @api public
|
|
294
|
+
# @return [Object] the delegated call's return value
|
|
295
|
+
# @example
|
|
296
|
+
# MultiJson.parse('{"a":1}') # delegates to MultiJSON.parse
|
|
297
|
+
# rubocop:disable Naming/BlockForwarding, Style/ArgumentsForwarding
|
|
298
|
+
def method_missing(name, *args, **kwargs, &block)
|
|
299
|
+
::MultiJSON.warn_deprecation_once(:multi_json_constant,
|
|
300
|
+
"The MultiJson constant is deprecated and will be removed in v2.0. Use MultiJSON instead.")
|
|
301
|
+
if ::MultiJSON.respond_to?(name)
|
|
302
|
+
::MultiJSON.public_send(name, *args, **kwargs, &block)
|
|
303
|
+
else
|
|
304
|
+
super
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
# rubocop:enable Naming/BlockForwarding, Style/ArgumentsForwarding
|
|
308
|
+
|
|
309
|
+
# Respond to any method {MultiJSON} responds to
|
|
310
|
+
#
|
|
311
|
+
# @api public
|
|
312
|
+
# @param name [Symbol] method name
|
|
313
|
+
# @param include_private [Boolean] include private methods
|
|
314
|
+
# @return [Boolean] true if {MultiJSON} responds to the method
|
|
315
|
+
# @example
|
|
316
|
+
# MultiJson.respond_to?(:parse) #=> true
|
|
317
|
+
def respond_to_missing?(name, include_private)
|
|
318
|
+
::MultiJSON.respond_to?(name, include_private)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Resolve missing constants to their {MultiJSON} counterparts
|
|
322
|
+
#
|
|
323
|
+
# Enables ``rescue MultiJson::ParseError`` and
|
|
324
|
+
# ``MultiJson::Adapters::Oj`` to keep working during the
|
|
325
|
+
# deprecation cycle.
|
|
326
|
+
#
|
|
327
|
+
# @api public
|
|
328
|
+
# @param name [Symbol] constant name
|
|
329
|
+
# @return [Object] the resolved constant from {MultiJSON}
|
|
330
|
+
# @example
|
|
331
|
+
# MultiJson::ParseError # returns MultiJSON::ParseError
|
|
332
|
+
def const_missing(name)
|
|
333
|
+
::MultiJSON.warn_deprecation_once(:multi_json_constant,
|
|
334
|
+
"The MultiJson constant is deprecated and will be removed in v2.0. Use MultiJSON instead.")
|
|
335
|
+
::MultiJSON.const_get(name)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: multi_json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.21.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Bleigh
|
|
@@ -34,8 +34,6 @@ executables: []
|
|
|
34
34
|
extensions: []
|
|
35
35
|
extra_rdoc_files: []
|
|
36
36
|
files:
|
|
37
|
-
- CHANGELOG.md
|
|
38
|
-
- CONTRIBUTING.md
|
|
39
37
|
- LICENSE.md
|
|
40
38
|
- README.md
|
|
41
39
|
- lib/multi_json.rb
|
|
@@ -61,10 +59,10 @@ licenses:
|
|
|
61
59
|
- MIT
|
|
62
60
|
metadata:
|
|
63
61
|
bug_tracker_uri: https://github.com/sferik/multi_json/issues
|
|
64
|
-
changelog_uri: https://github.com/sferik/multi_json/blob/v1.
|
|
65
|
-
documentation_uri: https://www.rubydoc.info/gems/multi_json/1.
|
|
62
|
+
changelog_uri: https://github.com/sferik/multi_json/blob/v1.21.0/CHANGELOG.md
|
|
63
|
+
documentation_uri: https://www.rubydoc.info/gems/multi_json/1.21.0
|
|
66
64
|
rubygems_mfa_required: 'true'
|
|
67
|
-
source_code_uri: https://github.com/sferik/multi_json/tree/v1.
|
|
65
|
+
source_code_uri: https://github.com/sferik/multi_json/tree/v1.21.0
|
|
68
66
|
wiki_uri: https://github.com/sferik/multi_json/wiki
|
|
69
67
|
rdoc_options: []
|
|
70
68
|
require_paths:
|
|
@@ -80,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
80
78
|
- !ruby/object:Gem::Version
|
|
81
79
|
version: '0'
|
|
82
80
|
requirements: []
|
|
83
|
-
rubygems_version: 4.0.
|
|
81
|
+
rubygems_version: 4.0.11
|
|
84
82
|
specification_version: 4
|
|
85
83
|
summary: A common interface to multiple JSON libraries.
|
|
86
84
|
test_files: []
|