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.
data/lib/multi_json.rb CHANGED
@@ -1,161 +1,268 @@
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
 
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
- include Options
9
- extend self
46
+ extend Options
47
+ extend AdapterSelector
10
48
 
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'
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
- self.load_options = self.dump_options = value
16
- end
55
+ class << self
56
+ private
17
57
 
18
- def default_options
19
- Kernel.warn "MultiJson.default_options is deprecated\n" \
20
- 'Use MultiJson.load_options or MultiJson.dump_options instead'
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
- load_options
23
- end
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
- Kernel.warn '[WARNING] MultiJson is using the default adapter (ok_json). ' \
63
- 'We recommend loading a different JSON library to improve performance.'
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
- :ok_json
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
- # Get the current adapter class.
70
- def adapter
71
- return @adapter if defined?(@adapter) && @adapter
109
+ # ===========================================================================
110
+ # Public API (module_function: class + private instance method)
111
+ # ===========================================================================
72
112
 
73
- use nil # load default adapter
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
- # Set the JSON parser utilizing a symbol, string, or class.
80
- # Supported by default are:
133
+ # Sets the adapter to use for JSON operations
81
134
  #
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)
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
- @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
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
- # Decode a JSON string into Ruby.
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
- # <b>Options</b>
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
- # <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.
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
- adapter = current_adapter(options)
178
+ adapter_class = current_adapter(options)
179
+ parse_error_class = MultiJson.parse_error_class_for(adapter_class)
121
180
  begin
122
- adapter.load(string, options)
123
- rescue adapter::ParseError => exception
124
- raise ParseError.build(exception, string)
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
- if (new_adapter = options[:adapter])
131
- load_adapter(new_adapter)
132
- else
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
- # Encodes a Ruby object as JSON.
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
- # Executes passed block using specified adapter.
144
- def with_adapter(new_adapter)
145
- old_adapter = adapter
146
- self.adapter = new_adapter
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
- self.adapter = old_adapter
245
+ Fiber[:multi_json_adapter] = previous_override
150
246
  end
151
- alias_method :with_engine, :with_adapter
152
247
 
153
- private
248
+ # ===========================================================================
249
+ # Private instance-method delegates for the singleton-only methods above
250
+ # ===========================================================================
251
+
252
+ private
154
253
 
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)
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.15.0
4
+ version: 1.20.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: []
@@ -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/adapters/gson.rb
64
- - lib/multi_json/adapters/jr_jackson.rb
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/ok_json.rb
34
+ - lib/multi_json/adapters/oj_common.rb
71
35
  - lib/multi_json/adapters/yajl.rb
72
- - lib/multi_json/convertible_hash_keys.rb
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/intridea/multi_json
43
+ homepage: https://github.com/sferik/multi_json
79
44
  licenses:
80
45
  - MIT
81
46
  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:
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: '0'
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: 1.3.5
65
+ version: '0'
101
66
  requirements: []
102
- rubygems_version: 3.0.3
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,11 +0,0 @@
1
- require 'json/pure'
2
- require 'multi_json/adapters/json_common'
3
-
4
- module MultiJson
5
- module Adapters
6
- # Use JSON pure to dump/load.
7
- class JsonPure < JsonCommon
8
- ParseError = ::JSON::ParserError
9
- end
10
- end
11
- 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