multi_json 1.15.0 → 1.20.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +272 -235
- data/CONTRIBUTING.md +23 -16
- data/LICENSE.md +1 -1
- data/README.md +128 -45
- data/lib/multi_json/adapter.rb +152 -19
- data/lib/multi_json/adapter_error.rb +35 -8
- data/lib/multi_json/adapter_selector.rb +194 -0
- data/lib/multi_json/adapters/fast_jsonparser.rb +72 -0
- data/lib/multi_json/adapters/json_gem.rb +81 -3
- data/lib/multi_json/adapters/oj.rb +71 -45
- data/lib/multi_json/adapters/oj_common.rb +44 -0
- data/lib/multi_json/adapters/yajl.rb +24 -3
- data/lib/multi_json/concurrency.rb +57 -0
- data/lib/multi_json/deprecated.rb +110 -0
- data/lib/multi_json/options.rb +83 -10
- data/lib/multi_json/options_cache/mutex_store.rb +65 -0
- data/lib/multi_json/options_cache.rb +76 -19
- data/lib/multi_json/parse_error.rb +95 -9
- data/lib/multi_json/version.rb +17 -4
- data/lib/multi_json.rb +226 -119
- metadata +22 -58
- data/lib/multi_json/adapters/gson.rb +0 -20
- data/lib/multi_json/adapters/jr_jackson.rb +0 -25
- data/lib/multi_json/adapters/json_common.rb +0 -23
- data/lib/multi_json/adapters/json_pure.rb +0 -11
- data/lib/multi_json/adapters/nsjsonserialization.rb +0 -35
- data/lib/multi_json/adapters/ok_json.rb +0 -23
- data/lib/multi_json/convertible_hash_keys.rb +0 -43
- data/lib/multi_json/vendor/okjson.rb +0 -606
data/lib/multi_json.rb
CHANGED
|
@@ -1,161 +1,268 @@
|
|
|
1
|
-
|
|
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
|
|
|
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"
|
|
10
|
+
|
|
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=``, ``load``, ``dump``,
|
|
23
|
+
# ``current_adapter``) so that both ``MultiJson.load(...)`` and legacy
|
|
24
|
+
# ``Class.new { include MultiJson }.new.send(:load, ...)`` 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``, etc.) lives in
|
|
33
|
+
# {file:lib/multi_json/deprecated.rb} so this file stays focused on the
|
|
34
|
+
# current surface.
|
|
35
|
+
#
|
|
36
|
+
# @example Basic usage
|
|
37
|
+
# MultiJson.load('{"foo":"bar"}') #=> {"foo" => "bar"}
|
|
38
|
+
# MultiJson.dump({foo: "bar"}) #=> '{"foo":"bar"}'
|
|
39
|
+
#
|
|
40
|
+
# @example Specifying an adapter
|
|
41
|
+
# MultiJson.use(:oj)
|
|
42
|
+
# MultiJson.load('{"foo":"bar"}', adapter: :json_gem)
|
|
43
|
+
#
|
|
44
|
+
# @api public
|
|
7
45
|
module MultiJson
|
|
8
|
-
|
|
9
|
-
extend
|
|
46
|
+
extend Options
|
|
47
|
+
extend AdapterSelector
|
|
10
48
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
14
54
|
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
class << self
|
|
56
|
+
private
|
|
17
57
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
58
|
+
# Emit a deprecation warning at most once per process for the given key
|
|
59
|
+
#
|
|
60
|
+
# Defined as a singleton method (rather than via module_function) so
|
|
61
|
+
# there is exactly one definition for mutation tests to target. The
|
|
62
|
+
# deprecated method bodies invoke this via ``warn_deprecation_once(...)``
|
|
63
|
+
# (singleton callers) and via the private instance delegates routing
|
|
64
|
+
# through the singleton for legacy ``include MultiJson`` consumers.
|
|
65
|
+
#
|
|
66
|
+
# @api private
|
|
67
|
+
# @param key [Symbol] identifier for the deprecation (typically the method name)
|
|
68
|
+
# @param message [String] warning message to emit on first call
|
|
69
|
+
# @return [void]
|
|
70
|
+
# @example
|
|
71
|
+
# MultiJson.send(:warn_deprecation_once, :foo, "MultiJson.foo is deprecated")
|
|
72
|
+
def warn_deprecation_once(key, message)
|
|
73
|
+
Concurrency.synchronize(:deprecation_warnings) do
|
|
74
|
+
return if DEPRECATION_WARNINGS_SHOWN.include?(key)
|
|
21
75
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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."
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
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
|
|
76
|
+
Kernel.warn(message)
|
|
77
|
+
DEPRECATION_WARNINGS_SHOWN.add(key)
|
|
59
78
|
end
|
|
60
79
|
end
|
|
80
|
+
end
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
# Resolve the ``ParseError`` constant for an adapter class
|
|
83
|
+
#
|
|
84
|
+
# The result is memoized on the adapter class itself in a
|
|
85
|
+
# ``@_multi_json_parse_error`` ivar so subsequent ``MultiJson.load``
|
|
86
|
+
# calls skip the constant lookup entirely. The lookup is performed
|
|
87
|
+
# with ``inherit: false`` so a stray top-level ``::ParseError``
|
|
88
|
+
# constant in the host process is correctly ignored on every
|
|
89
|
+
# supported Ruby implementation — TruffleRuby's ``::`` operator
|
|
90
|
+
# walks the ancestor chain and would otherwise pick up the top-level
|
|
91
|
+
# constant. Custom adapters that don't define their own
|
|
92
|
+
# ``ParseError`` get a clear {AdapterError} instead of the bare
|
|
93
|
+
# ``NameError`` Ruby would raise from the rescue clause.
|
|
94
|
+
#
|
|
95
|
+
# @api private
|
|
96
|
+
# @param adapter_class [Class] adapter class to inspect
|
|
97
|
+
# @return [Class] the adapter's ParseError class
|
|
98
|
+
# @raise [AdapterError] when the adapter doesn't define ParseError
|
|
99
|
+
def self.parse_error_class_for(adapter_class)
|
|
100
|
+
cached = adapter_class.instance_variable_get(:@_multi_json_parse_error)
|
|
101
|
+
return cached if cached
|
|
64
102
|
|
|
65
|
-
:
|
|
103
|
+
resolved = adapter_class.const_get(:ParseError, false)
|
|
104
|
+
adapter_class.instance_variable_set(:@_multi_json_parse_error, resolved)
|
|
105
|
+
rescue NameError
|
|
106
|
+
raise AdapterError, "Adapter #{adapter_class} must define a ParseError constant"
|
|
66
107
|
end
|
|
67
|
-
alias_method :default_engine, :default_adapter
|
|
68
108
|
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
109
|
+
# ===========================================================================
|
|
110
|
+
# Public API (module_function: class + private instance method)
|
|
111
|
+
# ===========================================================================
|
|
72
112
|
|
|
73
|
-
|
|
113
|
+
# @!visibility private
|
|
114
|
+
module_function
|
|
115
|
+
|
|
116
|
+
# Returns the current adapter class
|
|
117
|
+
#
|
|
118
|
+
# Honors a fiber-local override set by {.with_adapter} so concurrent
|
|
119
|
+
# blocks observe their own adapter without clobbering the process-wide
|
|
120
|
+
# default. Falls back to the process default when no override is set.
|
|
121
|
+
#
|
|
122
|
+
# @api public
|
|
123
|
+
# @return [Class] the current adapter class
|
|
124
|
+
# @example
|
|
125
|
+
# MultiJson.adapter #=> MultiJson::Adapters::Oj
|
|
126
|
+
def adapter
|
|
127
|
+
override = Fiber[:multi_json_adapter]
|
|
128
|
+
return override if override
|
|
74
129
|
|
|
75
|
-
@adapter
|
|
130
|
+
@adapter ||= use(nil)
|
|
76
131
|
end
|
|
77
|
-
alias_method :engine, :adapter
|
|
78
132
|
|
|
79
|
-
#
|
|
80
|
-
# Supported by default are:
|
|
133
|
+
# Sets the adapter to use for JSON operations
|
|
81
134
|
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
135
|
+
# The merged-options cache is only reset when the new adapter loads
|
|
136
|
+
# successfully. A failed ``use(:nonexistent)`` leaves the cache in
|
|
137
|
+
# place so the previously-active adapter keeps its cached entries.
|
|
138
|
+
#
|
|
139
|
+
# @api public
|
|
140
|
+
# @param new_adapter [Symbol, String, Module, nil] adapter specification
|
|
141
|
+
# @return [Class] the loaded adapter class
|
|
142
|
+
# @example
|
|
143
|
+
# MultiJson.use(:oj)
|
|
90
144
|
def use(new_adapter)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
|
145
|
+
loaded = load_adapter(new_adapter)
|
|
146
|
+
Concurrency.synchronize(:adapter) do
|
|
147
|
+
OptionsCache.reset
|
|
148
|
+
@adapter = loaded
|
|
108
149
|
end
|
|
109
|
-
rescue ::LoadError => exception
|
|
110
|
-
raise AdapterError.build(exception)
|
|
111
150
|
end
|
|
112
151
|
|
|
113
|
-
#
|
|
152
|
+
# Sets the adapter to use for JSON operations
|
|
153
|
+
#
|
|
154
|
+
# @api public
|
|
155
|
+
# @return [Class] the loaded adapter class
|
|
156
|
+
# @example
|
|
157
|
+
# MultiJson.adapter = :json_gem
|
|
158
|
+
alias_method :adapter=, :use
|
|
159
|
+
module_function :adapter=
|
|
160
|
+
|
|
161
|
+
# Parses a JSON string into a Ruby object
|
|
114
162
|
#
|
|
115
|
-
#
|
|
163
|
+
# Returns ``nil`` for ``nil``, empty, and whitespace-only inputs
|
|
164
|
+
# instead of raising. Pass an explicit non-blank string if you want
|
|
165
|
+
# to surface a {ParseError} for empty payloads at the call site.
|
|
116
166
|
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
167
|
+
# @api public
|
|
168
|
+
# @param string [String, #read] JSON string or IO-like object
|
|
169
|
+
# @param options [Hash] parsing options (adapter-specific)
|
|
170
|
+
# @return [Object, nil] parsed Ruby object, or nil for blank input
|
|
171
|
+
# @raise [ParseError] if parsing fails
|
|
172
|
+
# @raise [AdapterError] if the adapter doesn't define a ``ParseError`` constant
|
|
173
|
+
# @example
|
|
174
|
+
# MultiJson.load('{"foo":"bar"}') #=> {"foo" => "bar"}
|
|
175
|
+
# MultiJson.load("") #=> nil
|
|
176
|
+
# MultiJson.load(" \n") #=> nil
|
|
119
177
|
def load(string, options = {})
|
|
120
|
-
|
|
178
|
+
adapter_class = current_adapter(options)
|
|
179
|
+
parse_error_class = MultiJson.parse_error_class_for(adapter_class)
|
|
121
180
|
begin
|
|
122
|
-
|
|
123
|
-
rescue
|
|
124
|
-
raise ParseError.build(
|
|
181
|
+
adapter_class.load(string, options)
|
|
182
|
+
rescue parse_error_class => e
|
|
183
|
+
raise ParseError.build(e, string)
|
|
125
184
|
end
|
|
126
185
|
end
|
|
127
|
-
alias_method :decode, :load
|
|
128
186
|
|
|
187
|
+
# Returns the adapter to use for the given options
|
|
188
|
+
#
|
|
189
|
+
# ``nil`` is accepted as a no-options sentinel — explicit
|
|
190
|
+
# ``current_adapter(nil)`` calls fall through to the process default
|
|
191
|
+
# adapter without raising.
|
|
192
|
+
#
|
|
193
|
+
# @api public
|
|
194
|
+
# @param options [Hash, nil] options that may contain :adapter key, or
|
|
195
|
+
# nil to use the process default
|
|
196
|
+
# @return [Class] adapter class
|
|
197
|
+
# @example
|
|
198
|
+
# MultiJson.current_adapter(adapter: :oj) #=> MultiJson::Adapters::Oj
|
|
129
199
|
def current_adapter(options = {})
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
adapter
|
|
134
|
-
end
|
|
200
|
+
options ||= Options::EMPTY_OPTIONS
|
|
201
|
+
adapter_override = options[:adapter]
|
|
202
|
+
adapter_override ? load_adapter(adapter_override) : adapter
|
|
135
203
|
end
|
|
136
204
|
|
|
137
|
-
#
|
|
205
|
+
# Serializes a Ruby object to a JSON string
|
|
206
|
+
#
|
|
207
|
+
# @api public
|
|
208
|
+
# @param object [Object] object to serialize
|
|
209
|
+
# @param options [Hash] serialization options (adapter-specific)
|
|
210
|
+
# @return [String] JSON string
|
|
211
|
+
# @example
|
|
212
|
+
# MultiJson.dump({foo: "bar"}) #=> '{"foo":"bar"}'
|
|
138
213
|
def dump(object, options = {})
|
|
139
214
|
current_adapter(options).dump(object, options)
|
|
140
215
|
end
|
|
141
|
-
alias_method :encode, :dump
|
|
142
216
|
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
217
|
+
# Re-publicize the instance versions of the module_function methods so
|
|
218
|
+
# YARD/yardstick render them as part of the public API and legacy
|
|
219
|
+
# ``include MultiJson`` consumers can call them without ``.send``.
|
|
220
|
+
public :adapter, :use, :adapter=, :load, :current_adapter, :dump
|
|
221
|
+
|
|
222
|
+
# ===========================================================================
|
|
223
|
+
# Public API (def self.foo: singleton-only, for mutation-test precision)
|
|
224
|
+
# ===========================================================================
|
|
225
|
+
|
|
226
|
+
# Executes a block using the specified adapter
|
|
227
|
+
#
|
|
228
|
+
# Defined as a singleton method so mutation testing has exactly one
|
|
229
|
+
# definition to target. The override is stored in fiber-local storage
|
|
230
|
+
# so concurrent fibers and threads each see their own adapter without
|
|
231
|
+
# racing on a shared module variable; nested calls save and restore
|
|
232
|
+
# the previous fiber-local value.
|
|
233
|
+
#
|
|
234
|
+
# @api public
|
|
235
|
+
# @param new_adapter [Symbol, String, Module] adapter to use
|
|
236
|
+
# @yield block to execute with the temporary adapter
|
|
237
|
+
# @return [Object] result of the block
|
|
238
|
+
# @example
|
|
239
|
+
# MultiJson.with_adapter(:json_gem) { MultiJson.dump({}) }
|
|
240
|
+
def self.with_adapter(new_adapter)
|
|
241
|
+
previous_override = Fiber[:multi_json_adapter]
|
|
242
|
+
Fiber[:multi_json_adapter] = load_adapter(new_adapter)
|
|
147
243
|
yield
|
|
148
244
|
ensure
|
|
149
|
-
|
|
245
|
+
Fiber[:multi_json_adapter] = previous_override
|
|
150
246
|
end
|
|
151
|
-
alias_method :with_engine, :with_adapter
|
|
152
247
|
|
|
153
|
-
|
|
248
|
+
# ===========================================================================
|
|
249
|
+
# Private instance-method delegates for the singleton-only methods above
|
|
250
|
+
# ===========================================================================
|
|
251
|
+
|
|
252
|
+
private
|
|
154
253
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
254
|
+
# Instance-method delegate for {MultiJson.with_adapter}
|
|
255
|
+
#
|
|
256
|
+
# @api private
|
|
257
|
+
# @param new_adapter [Symbol, String, Module] adapter to use
|
|
258
|
+
# @yield block to execute with the temporary adapter
|
|
259
|
+
# @return [Object] result of the block
|
|
260
|
+
# @example
|
|
261
|
+
# class Foo; include MultiJson; end
|
|
262
|
+
# Foo.new.send(:with_adapter, :json_gem) { ... }
|
|
263
|
+
def with_adapter(new_adapter, &)
|
|
264
|
+
MultiJson.with_adapter(new_adapter, &)
|
|
160
265
|
end
|
|
161
266
|
end
|
|
267
|
+
|
|
268
|
+
require_relative "multi_json/deprecated"
|
metadata
CHANGED
|
@@ -1,54 +1,21 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: multi_json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.20.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Bleigh
|
|
8
8
|
- Josh Kalderimis
|
|
9
|
-
- Erik
|
|
9
|
+
- Erik Berlin
|
|
10
10
|
- Pavel Pravosud
|
|
11
|
-
autorequire:
|
|
12
11
|
bindir: bin
|
|
13
12
|
cert_chain: []
|
|
14
|
-
date:
|
|
15
|
-
dependencies:
|
|
16
|
-
|
|
17
|
-
|
|
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: []
|
|
@@ -60,31 +27,29 @@ files:
|
|
|
60
27
|
- lib/multi_json.rb
|
|
61
28
|
- lib/multi_json/adapter.rb
|
|
62
29
|
- lib/multi_json/adapter_error.rb
|
|
63
|
-
- lib/multi_json/
|
|
64
|
-
- lib/multi_json/adapters/
|
|
65
|
-
- lib/multi_json/adapters/json_common.rb
|
|
30
|
+
- lib/multi_json/adapter_selector.rb
|
|
31
|
+
- lib/multi_json/adapters/fast_jsonparser.rb
|
|
66
32
|
- lib/multi_json/adapters/json_gem.rb
|
|
67
|
-
- lib/multi_json/adapters/json_pure.rb
|
|
68
|
-
- lib/multi_json/adapters/nsjsonserialization.rb
|
|
69
33
|
- lib/multi_json/adapters/oj.rb
|
|
70
|
-
- lib/multi_json/adapters/
|
|
34
|
+
- lib/multi_json/adapters/oj_common.rb
|
|
71
35
|
- lib/multi_json/adapters/yajl.rb
|
|
72
|
-
- lib/multi_json/
|
|
36
|
+
- lib/multi_json/concurrency.rb
|
|
37
|
+
- lib/multi_json/deprecated.rb
|
|
73
38
|
- lib/multi_json/options.rb
|
|
74
39
|
- lib/multi_json/options_cache.rb
|
|
40
|
+
- lib/multi_json/options_cache/mutex_store.rb
|
|
75
41
|
- lib/multi_json/parse_error.rb
|
|
76
|
-
- lib/multi_json/vendor/okjson.rb
|
|
77
42
|
- lib/multi_json/version.rb
|
|
78
|
-
homepage: https://github.com/
|
|
43
|
+
homepage: https://github.com/sferik/multi_json
|
|
79
44
|
licenses:
|
|
80
45
|
- MIT
|
|
81
46
|
metadata:
|
|
82
|
-
bug_tracker_uri: https://github.com/
|
|
83
|
-
changelog_uri: https://github.com/
|
|
84
|
-
documentation_uri: https://www.rubydoc.info/gems/multi_json/1.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
47
|
+
bug_tracker_uri: https://github.com/sferik/multi_json/issues
|
|
48
|
+
changelog_uri: https://github.com/sferik/multi_json/blob/v1.20.1/CHANGELOG.md
|
|
49
|
+
documentation_uri: https://www.rubydoc.info/gems/multi_json/1.20.1
|
|
50
|
+
rubygems_mfa_required: 'true'
|
|
51
|
+
source_code_uri: https://github.com/sferik/multi_json/tree/v1.20.1
|
|
52
|
+
wiki_uri: https://github.com/sferik/multi_json/wiki
|
|
88
53
|
rdoc_options: []
|
|
89
54
|
require_paths:
|
|
90
55
|
- lib
|
|
@@ -92,15 +57,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
92
57
|
requirements:
|
|
93
58
|
- - ">="
|
|
94
59
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
60
|
+
version: '3.2'
|
|
96
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
62
|
requirements:
|
|
98
63
|
- - ">="
|
|
99
64
|
- !ruby/object:Gem::Version
|
|
100
|
-
version:
|
|
65
|
+
version: '0'
|
|
101
66
|
requirements: []
|
|
102
|
-
rubygems_version:
|
|
103
|
-
signing_key:
|
|
67
|
+
rubygems_version: 4.0.10
|
|
104
68
|
specification_version: 4
|
|
105
69
|
summary: A common interface to multiple JSON libraries.
|
|
106
70
|
test_files: []
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require 'gson'
|
|
2
|
-
require 'stringio'
|
|
3
|
-
require 'multi_json/adapter'
|
|
4
|
-
|
|
5
|
-
module MultiJson
|
|
6
|
-
module Adapters
|
|
7
|
-
# Use the gson.rb library to dump/load.
|
|
8
|
-
class Gson < Adapter
|
|
9
|
-
ParseError = ::Gson::DecodeError
|
|
10
|
-
|
|
11
|
-
def load(string, options = {})
|
|
12
|
-
::Gson::Decoder.new(options).decode(string)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def dump(object, options = {})
|
|
16
|
-
::Gson::Encoder.new(options).encode(object)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require 'jrjackson' unless defined?(::JrJackson)
|
|
2
|
-
require 'multi_json/adapter'
|
|
3
|
-
|
|
4
|
-
module MultiJson
|
|
5
|
-
module Adapters
|
|
6
|
-
# Use the jrjackson.rb library to dump/load.
|
|
7
|
-
class JrJackson < Adapter
|
|
8
|
-
ParseError = ::JrJackson::ParseError
|
|
9
|
-
|
|
10
|
-
def load(string, options = {}) #:nodoc:
|
|
11
|
-
::JrJackson::Json.load(string, options)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
if ::JrJackson::Json.method(:dump).arity == 1
|
|
15
|
-
def dump(object, _)
|
|
16
|
-
::JrJackson::Json.dump(object)
|
|
17
|
-
end
|
|
18
|
-
else
|
|
19
|
-
def dump(object, options = {})
|
|
20
|
-
::JrJackson::Json.dump(object, options)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
require 'multi_json/adapter'
|
|
2
|
-
|
|
3
|
-
module MultiJson
|
|
4
|
-
module Adapters
|
|
5
|
-
class JsonCommon < Adapter
|
|
6
|
-
defaults :load, :create_additions => false, :quirks_mode => true
|
|
7
|
-
|
|
8
|
-
def load(string, options = {})
|
|
9
|
-
if string.respond_to?(:force_encoding)
|
|
10
|
-
string = string.dup.force_encoding(::Encoding::ASCII_8BIT)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
options[:symbolize_names] = true if options.delete(:symbolize_keys)
|
|
14
|
-
::JSON.parse(string, options)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def dump(object, options = {})
|
|
18
|
-
options.merge!(::JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty)
|
|
19
|
-
object.to_json(options)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# This adapter is here for legacy reasons. We can't really test it, so it's hard
|
|
2
|
-
# to tell if it's even working properly. If you're still using it, please
|
|
3
|
-
# consider migrating to any other adapter out there.
|
|
4
|
-
framework 'Foundation'
|
|
5
|
-
require 'multi_json/adapters/ok_json'
|
|
6
|
-
|
|
7
|
-
module MultiJson
|
|
8
|
-
module Adapters
|
|
9
|
-
class Nsjsonserialization < MultiJson::Adapters::OkJson
|
|
10
|
-
ParseError = ::MultiJson::OkJson::Error
|
|
11
|
-
|
|
12
|
-
def load(string, options = {})
|
|
13
|
-
data = string.dataUsingEncoding(NSUTF8StringEncoding)
|
|
14
|
-
object = NSJSONSerialization.JSONObjectWithData(data, :options => NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves, :error => nil)
|
|
15
|
-
if object
|
|
16
|
-
object = symbolize_keys(object) if options[:symbolize_keys]
|
|
17
|
-
object
|
|
18
|
-
else
|
|
19
|
-
super(string, options)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def dump(object, options = {})
|
|
24
|
-
pretty = options[:pretty] ? NSJSONWritingPrettyPrinted : 0
|
|
25
|
-
object = object.as_json if object.respond_to?(:as_json)
|
|
26
|
-
if NSJSONSerialization.isValidJSONObject(object)
|
|
27
|
-
data = NSJSONSerialization.dataWithJSONObject(object, :options => pretty, :error => nil)
|
|
28
|
-
NSMutableString.alloc.initWithData(data, :encoding => NSUTF8StringEncoding)
|
|
29
|
-
else
|
|
30
|
-
super(object, options)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
require 'multi_json/adapter'
|
|
2
|
-
require 'multi_json/convertible_hash_keys'
|
|
3
|
-
require 'multi_json/vendor/okjson'
|
|
4
|
-
|
|
5
|
-
module MultiJson
|
|
6
|
-
module Adapters
|
|
7
|
-
class OkJson < Adapter
|
|
8
|
-
include ConvertibleHashKeys
|
|
9
|
-
ParseError = ::MultiJson::OkJson::Error
|
|
10
|
-
|
|
11
|
-
def load(string, options = {})
|
|
12
|
-
result = ::MultiJson::OkJson.decode("[#{string}]").first
|
|
13
|
-
options[:symbolize_keys] ? symbolize_keys(result) : result
|
|
14
|
-
rescue ArgumentError # invalid byte sequence in UTF-8
|
|
15
|
-
raise ParseError
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def dump(object, _ = {})
|
|
19
|
-
::MultiJson::OkJson.valenc(stringify_keys(object))
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|