multi_json 1.15.0 → 1.21.1

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.
data/lib/multi_json.rb CHANGED
@@ -1,161 +1,320 @@
1
- require 'multi_json/options'
2
- require 'multi_json/version'
3
- require 'multi_json/adapter_error'
4
- require 'multi_json/parse_error'
5
- require 'multi_json/options_cache'
1
+ # frozen_string_literal: true
6
2
 
7
- module MultiJson
8
- include Options
9
- extend self
10
-
11
- def default_options=(value)
12
- Kernel.warn "MultiJson.default_options setter is deprecated\n" \
13
- 'Use MultiJson.load_options and MultiJson.dump_options instead'
3
+ require_relative "multi_json/concurrency"
4
+ require_relative "multi_json/options"
5
+ require_relative "multi_json/version"
6
+ require_relative "multi_json/adapter_error"
7
+ require_relative "multi_json/parse_error"
8
+ require_relative "multi_json/options_cache"
9
+ require_relative "multi_json/adapter_selector"
14
10
 
15
- self.load_options = self.dump_options = value
16
- end
11
+ # A unified interface for JSON libraries in Ruby
12
+ #
13
+ # MultiJSON allows swapping between JSON backends without changing your code.
14
+ # It auto-detects available JSON libraries and uses the fastest one available.
15
+ #
16
+ # ## Method-definition patterns
17
+ #
18
+ # The current public API uses two patterns, each chosen for a specific reason:
19
+ #
20
+ # 1. ``module_function`` creates both a class method and a private instance
21
+ # method from a single ``def``. This is used for the hot-path API
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
+ # work through the same body. The instance versions are re-publicized
26
+ # below so YARD renders them as part of the public API.
27
+ # 2. ``def self.foo`` creates only a singleton method, giving mutation
28
+ # testing a single canonical definition to target. This is used for
29
+ # {.with_adapter}, which needs precise mutation coverage of its
30
+ # fiber-local save/restore logic.
31
+ #
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
+ #
36
+ # @example Basic usage
37
+ # MultiJSON.parse('{"foo":"bar"}') #=> {"foo" => "bar"}
38
+ # MultiJSON.generate({foo: "bar"}) #=> '{"foo":"bar"}'
39
+ #
40
+ # @example Specifying an adapter
41
+ # MultiJSON.use(:oj)
42
+ # MultiJSON.parse('{"foo":"bar"}', adapter: :json_gem)
43
+ #
44
+ # @api public
45
+ module MultiJSON
46
+ extend Options
47
+ extend AdapterSelector
17
48
 
18
- def default_options
19
- Kernel.warn "MultiJson.default_options is deprecated\n" \
20
- 'Use MultiJson.load_options or MultiJson.dump_options instead'
49
+ # Tracks which deprecation warnings have already been emitted so each one
50
+ # fires at most once per process. Stored as a Set rather than a Hash so
51
+ # presence checks have unambiguous semantics for mutation tests.
52
+ DEPRECATION_WARNINGS_SHOWN = Set.new
53
+ private_constant :DEPRECATION_WARNINGS_SHOWN
21
54
 
22
- load_options
23
- end
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)
24
77
 
25
- %w(cached_options reset_cached_options!).each do |method_name|
26
- define_method method_name do |*|
27
- Kernel.warn "MultiJson.#{method_name} method is deprecated and no longer used."
78
+ Kernel.warn(message, category: :deprecated)
79
+ DEPRECATION_WARNINGS_SHOWN.add(key)
28
80
  end
29
81
  end
30
82
 
31
- ALIASES = {'jrjackson' => 'jr_jackson'}
32
-
33
- REQUIREMENT_MAP = [
34
- [:oj, 'oj'],
35
- [:yajl, 'yajl'],
36
- [:jr_jackson, 'jrjackson'],
37
- [:json_gem, 'json/ext'],
38
- [:gson, 'gson'],
39
- [:json_pure, 'json/pure'],
40
- ]
41
-
42
- # The default adapter based on what you currently
43
- # have loaded and installed. First checks to see
44
- # if any adapters are already loaded, then checks
45
- # to see which are installed if none are loaded.
46
- def default_adapter
47
- return :oj if defined?(::Oj)
48
- return :yajl if defined?(::Yajl)
49
- return :jr_jackson if defined?(::JrJackson)
50
- return :json_gem if defined?(::JSON::Ext::Parser)
51
- return :gson if defined?(::Gson)
52
-
53
- REQUIREMENT_MAP.each do |adapter, library|
54
- begin
55
- require library
56
- return adapter
57
- rescue ::LoadError
58
- next
59
- end
60
- end
61
-
62
- Kernel.warn '[WARNING] MultiJson is using the default adapter (ok_json). ' \
63
- 'We recommend loading a different JSON library to improve performance.'
83
+ # Resolve the ``ParseError`` constant for an adapter class
84
+ #
85
+ # The result is memoized on the adapter class itself in a
86
+ # ``@_multi_json_parse_error`` ivar so subsequent ``MultiJSON.load``
87
+ # calls skip the constant lookup entirely. The lookup is performed
88
+ # with ``inherit: false`` so a stray top-level ``::ParseError``
89
+ # constant in the host process is correctly ignored on every
90
+ # supported Ruby implementation — TruffleRuby's ``::`` operator
91
+ # walks the ancestor chain and would otherwise pick up the top-level
92
+ # constant. Custom adapters that don't define their own
93
+ # ``ParseError`` get a clear {AdapterError} instead of the bare
94
+ # ``NameError`` Ruby would raise from the rescue clause.
95
+ #
96
+ # @api private
97
+ # @param adapter_class [Class] adapter class to inspect
98
+ # @return [Class] the adapter's ParseError class
99
+ # @raise [AdapterError] when the adapter doesn't define ParseError
100
+ def self.parse_error_class_for(adapter_class)
101
+ cached = adapter_class.instance_variable_get(:@_multi_json_parse_error)
102
+ return cached if cached
64
103
 
65
- :ok_json
104
+ resolved = adapter_class.const_get(:ParseError, false)
105
+ adapter_class.instance_variable_set(:@_multi_json_parse_error, resolved)
106
+ rescue NameError
107
+ raise AdapterError, "Adapter #{adapter_class} must define a ParseError constant"
66
108
  end
67
- alias_method :default_engine, :default_adapter
68
109
 
69
- # Get the current adapter class.
70
- def adapter
71
- return @adapter if defined?(@adapter) && @adapter
110
+ # ===========================================================================
111
+ # Public API (module_function: class + private instance method)
112
+ # ===========================================================================
113
+
114
+ # @!visibility private
115
+ module_function
72
116
 
73
- use nil # load default adapter
117
+ # Returns the current adapter class
118
+ #
119
+ # Honors a fiber-local override set by {.with_adapter} so concurrent
120
+ # blocks observe their own adapter without clobbering the process-wide
121
+ # default. Falls back to the process default when no override is set.
122
+ #
123
+ # @api public
124
+ # @return [Class] the current adapter class
125
+ # @example
126
+ # MultiJSON.adapter #=> MultiJSON::Adapters::Oj
127
+ def adapter
128
+ override = Fiber[:multi_json_adapter]
129
+ return override if override
74
130
 
75
- @adapter
131
+ @adapter ||= use(nil)
76
132
  end
77
- alias_method :engine, :adapter
78
-
79
- # Set the JSON parser utilizing a symbol, string, or class.
80
- # Supported by default are:
81
- #
82
- # * <tt>:oj</tt>
83
- # * <tt>:json_gem</tt>
84
- # * <tt>:json_pure</tt>
85
- # * <tt>:ok_json</tt>
86
- # * <tt>:yajl</tt>
87
- # * <tt>:nsjsonserialization</tt> (MacRuby only)
88
- # * <tt>:gson</tt> (JRuby only)
89
- # * <tt>:jr_jackson</tt> (JRuby only)
133
+
134
+ # Sets the adapter to use for JSON operations
135
+ #
136
+ # The merged-options cache is only reset when the new adapter loads
137
+ # successfully. A failed ``use(:nonexistent)`` leaves the cache in
138
+ # place so the previously-active adapter keeps its cached entries.
139
+ #
140
+ # @api public
141
+ # @param new_adapter [Symbol, String, Module, nil] adapter specification
142
+ # @return [Class] the loaded adapter class
143
+ # @example
144
+ # MultiJSON.use(:oj)
90
145
  def use(new_adapter)
91
- @adapter = load_adapter(new_adapter)
92
- ensure
93
- OptionsCache.reset
94
- end
95
- alias_method :adapter=, :use
96
- alias_method :engine=, :use
97
-
98
- def load_adapter(new_adapter)
99
- case new_adapter
100
- when String, Symbol
101
- load_adapter_from_string_name new_adapter.to_s
102
- when NilClass, FalseClass
103
- load_adapter default_adapter
104
- when Class, Module
105
- new_adapter
106
- else
107
- fail ::LoadError, new_adapter
146
+ loaded = load_adapter(new_adapter)
147
+ Concurrency.synchronize(:adapter) do
148
+ OptionsCache.reset
149
+ @adapter = loaded
108
150
  end
109
- rescue ::LoadError => exception
110
- raise AdapterError.build(exception)
111
151
  end
112
152
 
113
- # Decode a JSON string into Ruby.
153
+ # Sets the adapter to use for JSON operations
114
154
  #
115
- # <b>Options</b>
155
+ # @api public
156
+ # @return [Class] the loaded adapter class
157
+ # @example
158
+ # MultiJSON.adapter = :json_gem
159
+ alias_method :adapter=, :use
160
+ module_function :adapter=
161
+
162
+ # Parses a JSON string into a Ruby object
163
+ #
164
+ # Returns ``nil`` for ``nil``, empty, and whitespace-only inputs
165
+ # instead of raising. Pass an explicit non-blank string if you want
166
+ # to surface a {ParseError} for empty payloads at the call site.
116
167
  #
117
- # <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
118
- # <tt>:adapter</tt> :: If set, the selected adapter will be used for this call.
119
- def load(string, options = {})
120
- adapter = current_adapter(options)
168
+ # @api public
169
+ # @param string [String, #read] JSON string or IO-like object
170
+ # @param options [Hash] parsing options (adapter-specific)
171
+ # @return [Object, nil] parsed Ruby object, or nil for blank input
172
+ # @raise [ParseError] if parsing fails
173
+ # @raise [AdapterError] if the adapter doesn't define a ``ParseError`` constant
174
+ # @example
175
+ # MultiJSON.parse('{"foo":"bar"}') #=> {"foo" => "bar"}
176
+ # MultiJSON.parse("") #=> nil
177
+ # MultiJSON.parse(" \n") #=> nil
178
+ def parse(string, options = {})
179
+ adapter_class = current_adapter(options)
180
+ parse_error_class = MultiJSON.parse_error_class_for(adapter_class)
121
181
  begin
122
- adapter.load(string, options)
123
- rescue adapter::ParseError => exception
124
- raise ParseError.build(exception, string)
182
+ adapter_class.load(string, options)
183
+ rescue parse_error_class => e
184
+ raise ParseError.build(e, string)
125
185
  end
126
186
  end
127
- alias_method :decode, :load
128
187
 
188
+ # Returns the adapter to use for the given options
189
+ #
190
+ # ``nil`` is accepted as a no-options sentinel — explicit
191
+ # ``current_adapter(nil)`` calls fall through to the process default
192
+ # adapter without raising.
193
+ #
194
+ # @api public
195
+ # @param options [Hash, nil] options that may contain :adapter key, or
196
+ # nil to use the process default
197
+ # @return [Class] adapter class
198
+ # @example
199
+ # MultiJSON.current_adapter(adapter: :oj) #=> MultiJSON::Adapters::Oj
129
200
  def current_adapter(options = {})
130
- if (new_adapter = options[:adapter])
131
- load_adapter(new_adapter)
132
- else
133
- adapter
134
- end
201
+ options ||= Options::EMPTY_OPTIONS
202
+ adapter_override = options[:adapter]
203
+ adapter_override ? load_adapter(adapter_override) : adapter
135
204
  end
136
205
 
137
- # Encodes a Ruby object as JSON.
138
- def dump(object, options = {})
206
+ # Serializes a Ruby object to a JSON string
207
+ #
208
+ # @api public
209
+ # @param object [Object] object to serialize
210
+ # @param options [Hash] serialization options (adapter-specific)
211
+ # @return [String] JSON string
212
+ # @example
213
+ # MultiJSON.generate({foo: "bar"}) #=> '{"foo":"bar"}'
214
+ def generate(object, options = {})
139
215
  current_adapter(options).dump(object, options)
140
216
  end
141
- alias_method :encode, :dump
142
217
 
143
- # Executes passed block using specified adapter.
144
- def with_adapter(new_adapter)
145
- old_adapter = adapter
146
- self.adapter = new_adapter
218
+ # Re-publicize the instance versions of the module_function methods so
219
+ # YARD/yardstick render them as part of the public API and legacy
220
+ # ``include MultiJSON`` consumers can call them without ``.send``.
221
+ public :adapter, :use, :adapter=, :parse, :current_adapter, :generate
222
+
223
+ # ===========================================================================
224
+ # Public API (def self.foo: singleton-only, for mutation-test precision)
225
+ # ===========================================================================
226
+
227
+ # Executes a block using the specified adapter
228
+ #
229
+ # Defined as a singleton method so mutation testing has exactly one
230
+ # definition to target. The override is stored in fiber-local storage
231
+ # so concurrent fibers and threads each see their own adapter without
232
+ # racing on a shared module variable; nested calls save and restore
233
+ # the previous fiber-local value.
234
+ #
235
+ # @api public
236
+ # @param new_adapter [Symbol, String, Module] adapter to use
237
+ # @yield block to execute with the temporary adapter
238
+ # @return [Object] result of the block
239
+ # @example
240
+ # MultiJSON.with_adapter(:json_gem) { MultiJSON.dump({}) }
241
+ def self.with_adapter(new_adapter)
242
+ previous_override = Fiber[:multi_json_adapter]
243
+ Fiber[:multi_json_adapter] = load_adapter(new_adapter)
147
244
  yield
148
245
  ensure
149
- self.adapter = old_adapter
246
+ Fiber[:multi_json_adapter] = previous_override
150
247
  end
151
- alias_method :with_engine, :with_adapter
152
248
 
153
- private
249
+ # ===========================================================================
250
+ # Private instance-method delegates for the singleton-only methods above
251
+ # ===========================================================================
154
252
 
155
- def load_adapter_from_string_name(name)
156
- name = ALIASES.fetch(name, name)
157
- require "multi_json/adapters/#{name.downcase}"
158
- klass_name = name.to_s.split('_').map(&:capitalize) * ''
159
- MultiJson::Adapters.const_get(klass_name)
253
+ private
254
+
255
+ # Instance-method delegate for {MultiJSON.with_adapter}
256
+ #
257
+ # @api private
258
+ # @param new_adapter [Symbol, String, Module] adapter to use
259
+ # @yield block to execute with the temporary adapter
260
+ # @return [Object] result of the block
261
+ # @example
262
+ # class Foo; include MultiJSON; end
263
+ # Foo.new.send(:with_adapter, :json_gem) { ... }
264
+ def with_adapter(new_adapter, &)
265
+ MultiJSON.with_adapter(new_adapter, &)
266
+ end
267
+ end
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``. Each public
276
+ # method on {MultiJSON} gets an explicit forwarder defined on this
277
+ # module, and constant access resolves via {.const_missing}, so both
278
+ # dotted calls and ``::`` constant lookups (including rescue clauses)
279
+ # route through the canonical module.
280
+ #
281
+ # @api public
282
+ # @deprecated Use {MultiJSON} (all-caps) instead. Will be removed in v2.0.
283
+ module MultiJson
284
+ # Forward every public method MultiJSON exposes through an explicit
285
+ # singleton method on the legacy MultiJson module, so callers that
286
+ # capture the method as a Method object (``MultiJson.method(:load)``)
287
+ # find this forwarder instead of falling back to inherited methods like
288
+ # ``Kernel#load``. The earlier ``method_missing``-based shim left
289
+ # ``MultiJson.method(:load)`` resolving to ``Kernel#load`` (because
290
+ # ``Module#method`` doesn't consult ``method_missing``) and broke
291
+ # libraries (Sawyer, Octokit, Danger) that capture decoders as Method
292
+ # objects. Forwarding eagerly fixes the capture path while preserving
293
+ # the one-time deprecation warning each call emits.
294
+ (::MultiJSON.public_methods - ::Module.public_methods).each do |forwarded|
295
+ define_singleton_method(forwarded) do |*args, **kwargs, &block|
296
+ ::MultiJSON.warn_deprecation_once(:multi_json_constant,
297
+ "The MultiJson constant is deprecated and will be removed in v2.0. Use MultiJSON instead.")
298
+ ::MultiJSON.public_send(forwarded, *args, **kwargs, &block)
299
+ end
300
+ end
301
+
302
+ class << self
303
+ # Resolve missing constants to their {MultiJSON} counterparts
304
+ #
305
+ # Enables ``rescue MultiJson::ParseError`` and
306
+ # ``MultiJson::Adapters::Oj`` to keep working during the
307
+ # deprecation cycle.
308
+ #
309
+ # @api public
310
+ # @param name [Symbol] constant name
311
+ # @return [Object] the resolved constant from {MultiJSON}
312
+ # @example
313
+ # MultiJson::ParseError # returns MultiJSON::ParseError
314
+ def const_missing(name)
315
+ ::MultiJSON.warn_deprecation_once(:multi_json_constant,
316
+ "The MultiJson constant is deprecated and will be removed in v2.0. Use MultiJSON instead.")
317
+ ::MultiJSON.const_get(name)
318
+ end
160
319
  end
161
320
  end
metadata CHANGED
@@ -1,90 +1,53 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
4
+ version: 1.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  - Josh Kalderimis
9
- - Erik Michaels-Ober
9
+ - Erik Berlin
10
10
  - Pavel Pravosud
11
- autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2020-07-10 00:00:00.000000000 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: rake
18
- requirement: !ruby/object:Gem::Requirement
19
- requirements:
20
- - - "~>"
21
- - !ruby/object:Gem::Version
22
- version: '10.5'
23
- type: :development
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '10.5'
30
- - !ruby/object:Gem::Dependency
31
- name: rspec
32
- requirement: !ruby/object:Gem::Requirement
33
- requirements:
34
- - - "~>"
35
- - !ruby/object:Gem::Version
36
- version: '3.9'
37
- type: :development
38
- prerelease: false
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '3.9'
44
- description: A common interface to multiple JSON libraries, including Oj, Yajl, the
45
- JSON gem (with C-extensions), the pure-Ruby JSON gem, NSJSONSerialization, gson.rb,
46
- JrJackson, and OkJson.
13
+ date: 1980-01-02 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: A common interface to multiple JSON libraries, including fast_jsonparser,
16
+ Oj, Yajl, and the JSON gem.
47
17
  email:
48
- - michael@intridea.com
49
- - josh.kalderimis@gmail.com
50
18
  - sferik@gmail.com
51
- - pavel@pravosud.com
52
19
  executables: []
53
20
  extensions: []
54
21
  extra_rdoc_files: []
55
22
  files:
56
- - CHANGELOG.md
57
- - CONTRIBUTING.md
58
23
  - LICENSE.md
59
24
  - README.md
60
25
  - lib/multi_json.rb
61
26
  - lib/multi_json/adapter.rb
62
27
  - lib/multi_json/adapter_error.rb
63
- - lib/multi_json/adapters/gson.rb
64
- - lib/multi_json/adapters/jr_jackson.rb
65
- - lib/multi_json/adapters/json_common.rb
28
+ - lib/multi_json/adapter_selector.rb
29
+ - lib/multi_json/adapters/fast_jsonparser.rb
66
30
  - lib/multi_json/adapters/json_gem.rb
67
- - lib/multi_json/adapters/json_pure.rb
68
- - lib/multi_json/adapters/nsjsonserialization.rb
69
31
  - lib/multi_json/adapters/oj.rb
70
- - lib/multi_json/adapters/ok_json.rb
32
+ - lib/multi_json/adapters/oj_common.rb
71
33
  - lib/multi_json/adapters/yajl.rb
72
- - lib/multi_json/convertible_hash_keys.rb
34
+ - lib/multi_json/concurrency.rb
35
+ - lib/multi_json/deprecated.rb
73
36
  - lib/multi_json/options.rb
74
37
  - lib/multi_json/options_cache.rb
38
+ - lib/multi_json/options_cache/mutex_store.rb
75
39
  - lib/multi_json/parse_error.rb
76
- - lib/multi_json/vendor/okjson.rb
77
40
  - lib/multi_json/version.rb
78
- homepage: https://github.com/intridea/multi_json
41
+ homepage: https://github.com/sferik/multi_json
79
42
  licenses:
80
43
  - MIT
81
44
  metadata:
82
- bug_tracker_uri: https://github.com/intridea/multi_json/issues
83
- changelog_uri: https://github.com/intridea/multi_json/blob/v1.15.0/CHANGELOG.md
84
- documentation_uri: https://www.rubydoc.info/gems/multi_json/1.15.0
85
- source_code_uri: https://github.com/intridea/multi_json/tree/v1.15.0
86
- wiki_uri: https://github.com/intridea/multi_json/wiki
87
- post_install_message:
45
+ bug_tracker_uri: https://github.com/sferik/multi_json/issues
46
+ changelog_uri: https://github.com/sferik/multi_json/blob/v1.21.1/CHANGELOG.md
47
+ documentation_uri: https://www.rubydoc.info/gems/multi_json/1.21.1
48
+ rubygems_mfa_required: 'true'
49
+ source_code_uri: https://github.com/sferik/multi_json/tree/v1.21.1
50
+ wiki_uri: https://github.com/sferik/multi_json/wiki
88
51
  rdoc_options: []
89
52
  require_paths:
90
53
  - lib
@@ -92,15 +55,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
55
  requirements:
93
56
  - - ">="
94
57
  - !ruby/object:Gem::Version
95
- version: '0'
58
+ version: '3.2'
96
59
  required_rubygems_version: !ruby/object:Gem::Requirement
97
60
  requirements:
98
61
  - - ">="
99
62
  - !ruby/object:Gem::Version
100
- version: 1.3.5
63
+ version: '0'
101
64
  requirements: []
102
- rubygems_version: 3.0.3
103
- signing_key:
65
+ rubygems_version: 4.0.11
104
66
  specification_version: 4
105
67
  summary: A common interface to multiple JSON libraries.
106
68
  test_files: []