multi_json 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -0
- data/README.md +4 -0
- data/lib/multi_json.rb +28 -22
- data/lib/multi_json/adapter.rb +43 -0
- data/lib/multi_json/adapters/gson.rb +4 -5
- data/lib/multi_json/adapters/jrjackson.rb +22 -0
- data/lib/multi_json/adapters/json_common.rb +13 -23
- data/lib/multi_json/adapters/json_gem.rb +1 -2
- data/lib/multi_json/adapters/json_pure.rb +1 -2
- data/lib/multi_json/adapters/nsjsonserialization.rb +1 -2
- data/lib/multi_json/adapters/oj.rb +9 -10
- data/lib/multi_json/adapters/ok_json.rb +6 -42
- data/lib/multi_json/adapters/yajl.rb +4 -5
- data/lib/multi_json/convertible_hash_keys.rb +43 -0
- data/lib/multi_json/options.rb +39 -0
- data/lib/multi_json/version.rb +1 -1
- data/spec/adapter_shared_example.rb +73 -1
- data/spec/has_options.rb +74 -0
- data/spec/helper.rb +16 -29
- data/spec/json_common_shared_example.rb +8 -14
- data/spec/multi_json_spec.rb +45 -30
- metadata +9 -3
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
1.7.0
|
2
|
+
-----
|
3
|
+
* [Add load_options/dump_options to MultiJson](https://github.com/intridea/multi_json/commit/a153956be6b0df06ea1705ce3c1ff0b5b0e27ea5)
|
4
|
+
* [MultiJson does not modify arguments](https://github.com/intridea/multi_json/commit/58525b01c4c2f6635ba2ac13d6fd987b79f3962f)
|
5
|
+
* [Enable quirks_mode by default for json_gem/json_pure adapters](https://github.com/intridea/multi_json/commit/1fd4e6635c436515b7d7d5a0bee4548de8571520)
|
6
|
+
* [Add JrJackson adapter](https://github.com/intridea/multi_json/commit/4dd86fa96300aaaf6d762578b9b31ea82adb056d)
|
7
|
+
* [Raise ArgumentError on bad adapter input](https://github.com/intridea/multi_json/commit/911a3756bdff2cb5ac06497da3fa3e72199cb7ad)
|
8
|
+
|
1
9
|
1.6.1
|
2
10
|
-----
|
3
11
|
* [Revert "Use JSON.generate instead of #to_json"](https://github.com/intridea/multi_json/issues/86)
|
data/Gemfile
CHANGED
@@ -15,6 +15,7 @@ platforms :ruby, :mswin, :mingw do
|
|
15
15
|
end
|
16
16
|
platforms :jruby do
|
17
17
|
gem 'gson', '>= 0.6', :require => nil
|
18
|
+
gem 'jrjackson', :require => nil
|
18
19
|
end
|
19
20
|
|
20
21
|
group :development do
|
@@ -24,6 +25,7 @@ group :development do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
group :test do
|
28
|
+
gem 'coveralls', :require => false
|
27
29
|
gem 'rspec', '>= 2.11'
|
28
30
|
gem 'simplecov', :require => false
|
29
31
|
end
|
data/README.md
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
# MultiJSON
|
2
|
+
|
2
3
|
[![Gem Version](https://badge.fury.io/rb/multi_json.png)][gem]
|
3
4
|
[![Build Status](https://secure.travis-ci.org/intridea/multi_json.png?branch=master)][travis]
|
4
5
|
[![Dependency Status](https://gemnasium.com/intridea/multi_json.png?travis)][gemnasium]
|
5
6
|
[![Code Climate](https://codeclimate.com/github/intridea/multi_json.png)][codeclimate]
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/intridea/multi_json/badge.png?branch=master)][coveralls]
|
6
8
|
|
7
9
|
[gem]: https://rubygems.org/gems/multi_json
|
8
10
|
[travis]: http://travis-ci.org/intridea/multi_json
|
9
11
|
[gemnasium]: https://gemnasium.com/intridea/multi_json
|
10
12
|
[codeclimate]: https://codeclimate.com/github/intridea/multi_json
|
13
|
+
[coveralls]: https://coveralls.io/r/intridea/multi_json
|
11
14
|
|
12
15
|
Lots of Ruby libraries parse JSON and everyone has their favorite JSON coder.
|
13
16
|
Instead of choosing a single JSON coder and forcing users of your library to be
|
@@ -49,6 +52,7 @@ MultiJSON falls back to [OkJson][], a simple, vendorable JSON parser.
|
|
49
52
|
* [JSON Pure](https://github.com/flori/json) A Ruby variant of the JSON gem
|
50
53
|
* [NSJSONSerialization](https://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html) Wrapper for Apple's NSJSONSerialization in the Cocoa Framework (MacRuby only)
|
51
54
|
* [gson.rb](https://github.com/avsej/gson.rb) A Ruby wrapper for google-gson library (JRuby only)
|
55
|
+
* [JrJackson](https://github.com/guyboertje/jrjackson) JRuby wrapper for Jackson (JRuby only)
|
52
56
|
* [OkJson][okjson] A simple, vendorable JSON parser
|
53
57
|
|
54
58
|
## Supported Ruby Versions
|
data/lib/multi_json.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
require 'multi_json/options'
|
2
|
+
|
1
3
|
module MultiJson
|
4
|
+
include Options
|
2
5
|
extend self
|
3
6
|
|
4
7
|
class LoadError < StandardError
|
@@ -11,15 +14,24 @@ module MultiJson
|
|
11
14
|
end
|
12
15
|
DecodeError = LoadError # Legacy support
|
13
16
|
|
17
|
+
# Since `default_options` is deprecated, the
|
18
|
+
# reader is aliased to `dump_options` and the
|
19
|
+
# writer sets both `dump_options` and `load_options`
|
20
|
+
alias default_options dump_options
|
21
|
+
|
22
|
+
def default_options=(value)
|
23
|
+
Kernel.warn "MultiJson.default_options setter is deprecated\n" +
|
24
|
+
"Use MultiJson.load_options and MultiJson.dump_options instead"
|
14
25
|
|
15
|
-
|
16
|
-
|
26
|
+
self.load_options = self.dump_options = value
|
27
|
+
end
|
17
28
|
|
18
29
|
REQUIREMENT_MAP = [
|
19
30
|
['oj', :oj],
|
20
31
|
['yajl', :yajl],
|
21
32
|
['json', :json_gem],
|
22
33
|
['gson', :gson],
|
34
|
+
['jrjackson', :jrjackson],
|
23
35
|
['json/pure', :json_pure]
|
24
36
|
]
|
25
37
|
|
@@ -45,8 +57,7 @@ module MultiJson
|
|
45
57
|
Kernel.warn '[WARNING] MultiJson is using the default adapter (ok_json). We recommend loading a different JSON library to improve performance.'
|
46
58
|
:ok_json
|
47
59
|
end
|
48
|
-
|
49
|
-
alias :default_engine :default_adapter
|
60
|
+
alias default_engine default_adapter
|
50
61
|
|
51
62
|
# Get the current adapter class.
|
52
63
|
def adapter
|
@@ -56,8 +67,7 @@ module MultiJson
|
|
56
67
|
|
57
68
|
@adapter
|
58
69
|
end
|
59
|
-
|
60
|
-
alias :engine :adapter
|
70
|
+
alias engine adapter
|
61
71
|
|
62
72
|
# Set the JSON parser utilizing a symbol, string, or class.
|
63
73
|
# Supported by default are:
|
@@ -72,9 +82,8 @@ module MultiJson
|
|
72
82
|
def use(new_adapter)
|
73
83
|
@adapter = load_adapter(new_adapter)
|
74
84
|
end
|
75
|
-
alias
|
76
|
-
|
77
|
-
alias :engine= :use
|
85
|
+
alias adapter= use
|
86
|
+
alias engine= use
|
78
87
|
|
79
88
|
def load_adapter(new_adapter)
|
80
89
|
case new_adapter
|
@@ -86,8 +95,10 @@ module MultiJson
|
|
86
95
|
when Class, Module
|
87
96
|
new_adapter
|
88
97
|
else
|
89
|
-
raise
|
98
|
+
raise NameError
|
90
99
|
end
|
100
|
+
rescue NameError, ::LoadError
|
101
|
+
raise ArgumentError, 'Did not recognize your adapter specification.'
|
91
102
|
end
|
92
103
|
|
93
104
|
# Decode a JSON string into Ruby.
|
@@ -95,7 +106,7 @@ module MultiJson
|
|
95
106
|
# <b>Options</b>
|
96
107
|
#
|
97
108
|
# <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
|
98
|
-
# <tt>:adapter</tt> :: If set, the selected
|
109
|
+
# <tt>:adapter</tt> :: If set, the selected adapter will be used for this call.
|
99
110
|
def load(string, options={})
|
100
111
|
adapter = current_adapter(options)
|
101
112
|
begin
|
@@ -104,11 +115,10 @@ module MultiJson
|
|
104
115
|
raise LoadError.new(exception.message, exception.backtrace, string)
|
105
116
|
end
|
106
117
|
end
|
107
|
-
|
108
|
-
alias :decode :load
|
118
|
+
alias decode load
|
109
119
|
|
110
|
-
def current_adapter(options)
|
111
|
-
if new_adapter =
|
120
|
+
def current_adapter(options={})
|
121
|
+
if new_adapter = options[:adapter]
|
112
122
|
load_adapter(new_adapter)
|
113
123
|
else
|
114
124
|
adapter
|
@@ -117,12 +127,9 @@ module MultiJson
|
|
117
127
|
|
118
128
|
# Encodes a Ruby object as JSON.
|
119
129
|
def dump(object, options={})
|
120
|
-
options
|
121
|
-
adapter = current_adapter(options)
|
122
|
-
adapter.dump(object, options)
|
130
|
+
current_adapter(options).dump(object, options)
|
123
131
|
end
|
124
|
-
|
125
|
-
alias :encode :dump
|
132
|
+
alias encode dump
|
126
133
|
|
127
134
|
# Executes passed block using specified adapter.
|
128
135
|
def with_adapter(new_adapter)
|
@@ -131,7 +138,6 @@ module MultiJson
|
|
131
138
|
ensure
|
132
139
|
self.adapter = old_adapter
|
133
140
|
end
|
134
|
-
|
135
|
-
alias :with_engine :with_adapter
|
141
|
+
alias with_engine with_adapter
|
136
142
|
|
137
143
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'multi_json/options'
|
3
|
+
|
4
|
+
module MultiJson
|
5
|
+
class Adapter
|
6
|
+
extend Options
|
7
|
+
include Singleton
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def defaults(action, value)
|
11
|
+
metaclass = class << self; self; end
|
12
|
+
|
13
|
+
metaclass.instance_eval do
|
14
|
+
define_method("default_#{action}_options"){ value }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def load(string, options={})
|
19
|
+
instance.load(string, collect_load_options(string, options))
|
20
|
+
end
|
21
|
+
|
22
|
+
def dump(object, options={})
|
23
|
+
instance.dump(object, collect_dump_options(object, options))
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def collect_load_options(string, options)
|
29
|
+
collect_options :load_options, options, [ string, options ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def collect_dump_options(object, options)
|
33
|
+
collect_options :dump_options, options, [ object, options ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def collect_options(method, overrides, args)
|
37
|
+
global, local = *[MultiJson, self].map{ |r| r.send(method, *args) }
|
38
|
+
local.merge(global).merge(overrides)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'gson' unless defined?(::Gson)
|
2
|
+
require 'multi_json/adapter'
|
2
3
|
|
3
4
|
module MultiJson
|
4
5
|
module Adapters
|
5
6
|
# Use the gson.rb library to dump/load.
|
6
|
-
|
7
|
-
extend self
|
8
|
-
|
7
|
+
class Gson < Adapter
|
9
8
|
ParseError = ::Gson::DecodeError
|
10
9
|
|
11
|
-
def load(string, options={})
|
10
|
+
def load(string, options={})
|
12
11
|
::Gson::Decoder.new(options).decode(string)
|
13
12
|
end
|
14
13
|
|
15
|
-
def dump(object, options={})
|
14
|
+
def dump(object, options={})
|
16
15
|
::Gson::Encoder.new(options).encode(object)
|
17
16
|
end
|
18
17
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'jrjackson_r' unless defined?(::JrJackson)
|
2
|
+
require 'multi_json/adapter'
|
3
|
+
require 'multi_json/convertible_hash_keys'
|
4
|
+
|
5
|
+
module MultiJson
|
6
|
+
module Adapters
|
7
|
+
class Jrjackson < Adapter
|
8
|
+
include ConvertibleHashKeys
|
9
|
+
ParseError = ::Java::OrgCodehausJackson::JsonParseException
|
10
|
+
|
11
|
+
def load(string, options={})
|
12
|
+
string = string.read if string.respond_to?(:read)
|
13
|
+
result = ::JrJackson::Json.parse(string)
|
14
|
+
options[:symbolize_keys] ? symbolize_keys(result) : result
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump(object, options={})
|
18
|
+
::JrJackson::Json.generate(stringify_keys(object))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,35 +1,25 @@
|
|
1
|
+
require 'multi_json/adapter'
|
2
|
+
|
1
3
|
module MultiJson
|
2
4
|
module Adapters
|
3
|
-
|
5
|
+
class JsonCommon < Adapter
|
6
|
+
defaults :load, :create_additions => false, :quirks_mode => true
|
7
|
+
|
4
8
|
def load(string, options={})
|
5
9
|
string = string.read if string.respond_to?(:read)
|
6
|
-
::JSON.parse("[#{string}]", process_load_options!(options)).first
|
7
|
-
end
|
8
|
-
|
9
|
-
def dump(object, options={})
|
10
|
-
object.to_json(process_dump_options!(options))
|
11
|
-
end
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
def process_load_options!(options={})
|
16
|
-
process_options!({:create_additions => false}, options) do |opts|
|
17
|
-
opts.merge!(:symbolize_names => true) if options.delete(:symbolize_keys)
|
11
|
+
if string.respond_to?(:force_encoding)
|
12
|
+
string = string.dup.force_encoding(::Encoding::ASCII_8BIT)
|
18
13
|
end
|
19
|
-
end
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
opts.merge!(::JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty)
|
24
|
-
end
|
15
|
+
options[:symbolize_names] = true if options.delete(:symbolize_keys)
|
16
|
+
::JSON.parse(string, options)
|
25
17
|
end
|
26
18
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
default_options.merge!(options)
|
19
|
+
def dump(object, options={})
|
20
|
+
options.merge!(::JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty)
|
21
|
+
object.to_json(options)
|
31
22
|
end
|
32
|
-
|
33
23
|
end
|
34
24
|
end
|
35
|
-
end
|
25
|
+
end
|
@@ -3,8 +3,7 @@ require 'multi_json/adapters/ok_json'
|
|
3
3
|
|
4
4
|
module MultiJson
|
5
5
|
module Adapters
|
6
|
-
|
7
|
-
extend self, MultiJson::Adapters::OkJson
|
6
|
+
class Nsjsonserialization < MultiJson::Adapters::OkJson
|
8
7
|
ParseError = ::MultiJson::OkJson::Error
|
9
8
|
|
10
9
|
def load(string, options={})
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'oj' unless defined?(::Oj)
|
2
|
+
require 'multi_json/adapter'
|
2
3
|
|
3
4
|
module MultiJson
|
4
5
|
module Adapters
|
5
6
|
# Use the Oj library to dump/load.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
DEFAULT_OPTIONS = {:mode => :compat, :time_format => :ruby}.freeze
|
7
|
+
class Oj < Adapter
|
8
|
+
defaults :load, :mode => :strict
|
9
|
+
defaults :dump, :mode => :compat, :time_format => :ruby
|
10
10
|
|
11
11
|
ParseError = if defined?(::Oj::ParseError)
|
12
12
|
::Oj::ParseError
|
@@ -14,15 +14,14 @@ module MultiJson
|
|
14
14
|
SyntaxError
|
15
15
|
end
|
16
16
|
|
17
|
-
def load(string, options={})
|
18
|
-
options
|
19
|
-
options
|
20
|
-
::Oj.load(string, DEFAULT_OPTIONS.merge(options))
|
17
|
+
def load(string, options={})
|
18
|
+
options[:symbol_keys] = true if options.delete(:symbolize_keys)
|
19
|
+
::Oj.load(string, options)
|
21
20
|
end
|
22
21
|
|
23
|
-
def dump(object, options={})
|
22
|
+
def dump(object, options={})
|
24
23
|
options.merge!(:indent => 2) if options[:pretty]
|
25
|
-
::Oj.dump(object,
|
24
|
+
::Oj.dump(object, options)
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
@@ -1,58 +1,22 @@
|
|
1
|
+
require 'multi_json/adapter'
|
2
|
+
require 'multi_json/convertible_hash_keys'
|
1
3
|
require 'multi_json/vendor/okjson'
|
2
4
|
|
3
5
|
module MultiJson
|
4
6
|
module Adapters
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
class OkJson < Adapter
|
8
|
+
include ConvertibleHashKeys
|
8
9
|
ParseError = ::MultiJson::OkJson::Error
|
9
10
|
|
10
|
-
def load(string, options={})
|
11
|
+
def load(string, options={})
|
11
12
|
string = string.read if string.respond_to?(:read)
|
12
13
|
result = ::MultiJson::OkJson.decode("[#{string}]").first
|
13
14
|
options[:symbolize_keys] ? symbolize_keys(result) : result
|
14
15
|
end
|
15
16
|
|
16
|
-
def dump(object, options={})
|
17
|
+
def dump(object, options={})
|
17
18
|
::MultiJson::OkJson.valenc(stringify_keys(object))
|
18
19
|
end
|
19
|
-
|
20
|
-
def symbolize_keys(object) #:nodoc:
|
21
|
-
prepare_object(object) do |key|
|
22
|
-
key.is_a?(String) ? key.to_sym : key
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def stringify_keys(object) #:nodoc:
|
27
|
-
prepare_object(object) do |key|
|
28
|
-
key.respond_to?(:to_s) ? key.to_s : key
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def prepare_object(object, &key_modifier) #:nodoc:
|
33
|
-
case object
|
34
|
-
when Array
|
35
|
-
object.map do |value|
|
36
|
-
prepare_object(value, &key_modifier)
|
37
|
-
end
|
38
|
-
when Hash
|
39
|
-
object.inject({}) do |result, (key, value)|
|
40
|
-
new_key = key_modifier.call(key)
|
41
|
-
new_value = prepare_object(value, &key_modifier)
|
42
|
-
result.merge! new_key => new_value
|
43
|
-
end
|
44
|
-
when String, Numeric, true, false, nil
|
45
|
-
object
|
46
|
-
else
|
47
|
-
if object.respond_to?(:to_json)
|
48
|
-
object
|
49
|
-
elsif object.respond_to?(:to_s)
|
50
|
-
object.to_s
|
51
|
-
else
|
52
|
-
object
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
20
|
end
|
57
21
|
end
|
58
22
|
end
|
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'yajl' unless defined?(::Yajl)
|
2
|
+
require 'multi_json/adapter'
|
2
3
|
|
3
4
|
module MultiJson
|
4
5
|
module Adapters
|
5
6
|
# Use the Yajl-Ruby library to dump/load.
|
6
|
-
|
7
|
-
extend self
|
8
|
-
|
7
|
+
class Yajl < Adapter
|
9
8
|
ParseError = ::Yajl::ParseError
|
10
9
|
|
11
|
-
def load(string, options={})
|
10
|
+
def load(string, options={})
|
12
11
|
::Yajl::Parser.new(:symbolize_keys => options[:symbolize_keys]).parse(string)
|
13
12
|
end
|
14
13
|
|
15
|
-
def dump(object, options={})
|
14
|
+
def dump(object, options={})
|
16
15
|
::Yajl::Encoder.encode(object, options)
|
17
16
|
end
|
18
17
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module MultiJson
|
2
|
+
module ConvertibleHashKeys
|
3
|
+
private
|
4
|
+
|
5
|
+
def symbolize_keys(object)
|
6
|
+
prepare_object(object) do |key|
|
7
|
+
key.respond_to?(:to_sym) ? key.to_sym : key
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def stringify_keys(object)
|
12
|
+
prepare_object(object) do |key|
|
13
|
+
key.respond_to?(:to_s) ? key.to_s : key
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepare_object(object, &key_modifier)
|
18
|
+
return object unless block_given?
|
19
|
+
case object
|
20
|
+
when Array
|
21
|
+
object.map do |value|
|
22
|
+
prepare_object(value, &key_modifier)
|
23
|
+
end
|
24
|
+
when Hash
|
25
|
+
object.inject({}) do |result, (key, value)|
|
26
|
+
new_key = key_modifier.call(key)
|
27
|
+
new_value = prepare_object(value, &key_modifier)
|
28
|
+
result.merge! new_key => new_value
|
29
|
+
end
|
30
|
+
when String, Numeric, true, false, nil
|
31
|
+
object
|
32
|
+
else
|
33
|
+
if object.respond_to?(:to_json)
|
34
|
+
object
|
35
|
+
elsif object.respond_to?(:to_s)
|
36
|
+
object.to_s
|
37
|
+
else
|
38
|
+
object
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MultiJson
|
2
|
+
module Options
|
3
|
+
attr_writer :load_options, :dump_options
|
4
|
+
|
5
|
+
def load_options(*args)
|
6
|
+
get_options :load_options, *args
|
7
|
+
end
|
8
|
+
|
9
|
+
def dump_options(*args)
|
10
|
+
get_options :dump_options, *args
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_load_options
|
14
|
+
@default_load_options ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_dump_options
|
18
|
+
@default_dump_options ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def get_options(ivar, *args)
|
24
|
+
defaults = send("default_#{ivar}")
|
25
|
+
|
26
|
+
return defaults unless instance_variable_defined?("@#{ivar}")
|
27
|
+
|
28
|
+
value = instance_variable_get("@#{ivar}")
|
29
|
+
|
30
|
+
if value.respond_to?(:call) and value.arity
|
31
|
+
value.arity == 0 ? value[] : value[*args]
|
32
|
+
elsif Hash === value or value.respond_to?(:to_hash)
|
33
|
+
value.to_hash
|
34
|
+
else
|
35
|
+
defaults
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/multi_json/version.rb
CHANGED
@@ -10,7 +10,38 @@ shared_examples_for 'an adapter' do |adapter|
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
it_behaves_like 'has options', lambda{ MultiJson.adapter }
|
14
|
+
|
15
|
+
it 'does not modify argument hashes' do
|
16
|
+
options = { :symbolize_keys => true, :pretty => false, :adapter => :json_gem }
|
17
|
+
expect{MultiJson.load('{}', options)}.to_not change{options}
|
18
|
+
expect{MultiJson.dump([42], options)}.to_not change{options}
|
19
|
+
end
|
20
|
+
|
13
21
|
describe '.dump' do
|
22
|
+
describe '#dump_options' do
|
23
|
+
before{ MultiJson.dump_options = MultiJson.adapter.dump_options = {} }
|
24
|
+
|
25
|
+
after do
|
26
|
+
MultiJson.adapter.instance.should_receive(:dump).with(1, :foo=>'bar', :fizz=>'buzz')
|
27
|
+
MultiJson.dump(1, :fizz => 'buzz')
|
28
|
+
MultiJson.dump_options = MultiJson.adapter.dump_options = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'respects global dump options' do
|
32
|
+
MultiJson.dump_options = {:foo => 'bar'}
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'respects per-adapter dump options' do
|
36
|
+
MultiJson.adapter.dump_options = {:foo => 'bar'}
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'adapter-specific are overridden by global options' do
|
40
|
+
MultiJson.adapter.dump_options = {:foo => 'foo'}
|
41
|
+
MultiJson.dump_options = {:foo => 'bar'}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
14
45
|
it 'writes decodable JSON' do
|
15
46
|
[
|
16
47
|
{'abc' => 'def'},
|
@@ -75,7 +106,7 @@ shared_examples_for 'an adapter' do |adapter|
|
|
75
106
|
|
76
107
|
# This behavior is currently not supported by gson.rb
|
77
108
|
# See discussion at https://github.com/intridea/multi_json/pull/71
|
78
|
-
unless adapter
|
109
|
+
unless %w(gson jrjackson).include?(adapter)
|
79
110
|
it 'dumps custom objects that implement to_json' do
|
80
111
|
klass = Class.new do
|
81
112
|
def to_json(*)
|
@@ -96,6 +127,47 @@ shared_examples_for 'an adapter' do |adapter|
|
|
96
127
|
end
|
97
128
|
|
98
129
|
describe '.load' do
|
130
|
+
describe '#load_options' do
|
131
|
+
before{ MultiJson.load_options = MultiJson.adapter.load_options = {} }
|
132
|
+
|
133
|
+
after do
|
134
|
+
MultiJson.adapter.instance.should_receive(:load).with('1', :foo => 'bar', :fizz => 'buzz')
|
135
|
+
MultiJson.load('1', :fizz => 'buzz')
|
136
|
+
MultiJson.load_options = MultiJson.adapter.load_options = nil
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'respects global load options' do
|
140
|
+
MultiJson.load_options = {:foo => 'bar'}
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'respects per-adapter load options' do
|
144
|
+
MultiJson.adapter.load_options = {:foo => 'bar'}
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'adapter-specific are overridden by global options' do
|
148
|
+
MultiJson.adapter.load_options = {:foo => 'foo'}
|
149
|
+
MultiJson.load_options = {:foo => 'bar'}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'does not modify input' do
|
154
|
+
input = %Q{\n\n {"foo":"bar"} \n\n\t}
|
155
|
+
expect{
|
156
|
+
MultiJson.load(input)
|
157
|
+
}.to_not change{ input }
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'does not modify input encoding' do
|
161
|
+
pending 'only in 1.9' unless RUBY_VERSION > '1.9'
|
162
|
+
|
163
|
+
input = '[123]'
|
164
|
+
input.force_encoding('iso-8859-1')
|
165
|
+
|
166
|
+
expect{
|
167
|
+
MultiJson.load(input)
|
168
|
+
}.to_not change{ input.encoding }
|
169
|
+
end
|
170
|
+
|
99
171
|
it 'properly loads valid JSON' do
|
100
172
|
expect(MultiJson.load('{"abc":"def"}')).to eq({'abc' => 'def'})
|
101
173
|
end
|
data/spec/has_options.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
shared_examples_for 'has options' do |object|
|
2
|
+
|
3
|
+
if object.respond_to?(:call)
|
4
|
+
subject{ object.call }
|
5
|
+
else
|
6
|
+
subject{ object }
|
7
|
+
end
|
8
|
+
|
9
|
+
%w(dump_options load_options).each do |getter|
|
10
|
+
|
11
|
+
let(:getter){ getter }
|
12
|
+
let(:default_getter){ "default_#{getter}" }
|
13
|
+
let(:setter){ "#{getter}=" }
|
14
|
+
let(:defaults){ subject.send(default_getter) }
|
15
|
+
let(:ivar){ "@#{getter}" }
|
16
|
+
|
17
|
+
describe getter.tr('_', ' ') do
|
18
|
+
before{ set nil }
|
19
|
+
after{ set nil }
|
20
|
+
|
21
|
+
def get(*args)
|
22
|
+
subject.send(getter, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(value)
|
26
|
+
subject.send(setter, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns default options if not set' do
|
30
|
+
expect(get).to eq(defaults)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'allows hashes' do
|
34
|
+
set :foo => 'bar'
|
35
|
+
expect(get).to eq(:foo => 'bar')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'allows objects that implement #to_hash' do
|
39
|
+
value = Class.new do
|
40
|
+
def to_hash
|
41
|
+
{:foo=>'bar'}
|
42
|
+
end
|
43
|
+
end.new
|
44
|
+
|
45
|
+
set value
|
46
|
+
expect(get).to eq(:foo => 'bar')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'evaluates lambda returning options (with args)' do
|
50
|
+
set lambda{ |a1, a2| { a1 => a2 }}
|
51
|
+
expect(get('1', '2')).to eq('1' => '2')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'evaluates lambda returning options (with no args)' do
|
55
|
+
set lambda{{:foo => 'bar'}}
|
56
|
+
expect(get).to eq(:foo => 'bar')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns empty hash in all other cases' do
|
60
|
+
set true
|
61
|
+
expect(get).to eq(defaults)
|
62
|
+
|
63
|
+
set false
|
64
|
+
expect(get).to eq(defaults)
|
65
|
+
|
66
|
+
set 10
|
67
|
+
expect(get).to eq(defaults)
|
68
|
+
|
69
|
+
set nil
|
70
|
+
expect(get).to eq(defaults)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/spec/helper.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
Coveralls::SimpleCov::Formatter
|
7
|
+
]
|
8
|
+
SimpleCov.start
|
7
9
|
|
8
10
|
require 'multi_json'
|
9
11
|
require 'rspec'
|
@@ -14,32 +16,17 @@ RSpec.configure do |config|
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
19
|
+
def silence_warnings
|
20
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
21
|
+
yield
|
22
|
+
ensure
|
23
|
+
$VERBOSE = old_verbose
|
24
|
+
end
|
25
|
+
|
17
26
|
def macruby?
|
18
27
|
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
|
19
28
|
end
|
20
29
|
|
21
30
|
def jruby?
|
22
31
|
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
23
|
-
end
|
24
|
-
|
25
|
-
class MockDecoder
|
26
|
-
def self.load(string, options={})
|
27
|
-
{'abc' => 'def'}
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.dump(string)
|
31
|
-
'{"abc":"def"}'
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
module MockModuleDecoder
|
36
|
-
extend self
|
37
|
-
|
38
|
-
def load(string, options={})
|
39
|
-
{'abc' => 'def'}
|
40
|
-
end
|
41
|
-
|
42
|
-
def dump(string)
|
43
|
-
'{"abc":"def"}'
|
44
|
-
end
|
45
|
-
end
|
32
|
+
end
|
@@ -1,17 +1,13 @@
|
|
1
1
|
shared_examples_for 'JSON-like adapter' do |adapter|
|
2
|
-
before
|
3
|
-
begin
|
4
|
-
MultiJson.use adapter
|
5
|
-
rescue LoadError
|
6
|
-
pending "Adapter #{adapter} couldn't be loaded (not installed?)"
|
7
|
-
end
|
8
|
-
end
|
2
|
+
before{ MultiJson.use adapter }
|
9
3
|
|
10
4
|
describe '.dump' do
|
5
|
+
before{ MultiJson.dump_options = MultiJson.adapter.dump_options = nil }
|
6
|
+
|
11
7
|
describe 'with :pretty option set to true' do
|
12
8
|
it 'passes default pretty options' do
|
13
9
|
object = 'foo'
|
14
|
-
object.should_receive(:to_json).with(JSON::PRETTY_STATE_PROTOTYPE.to_h)
|
10
|
+
object.should_receive(:to_json).with(JSON::PRETTY_STATE_PROTOTYPE.to_h)
|
15
11
|
MultiJson.dump(object, :pretty => true)
|
16
12
|
end
|
17
13
|
end
|
@@ -19,18 +15,16 @@ shared_examples_for 'JSON-like adapter' do |adapter|
|
|
19
15
|
describe 'with :indent option' do
|
20
16
|
it 'passes it on dump' do
|
21
17
|
object = 'foo'
|
22
|
-
object.should_receive(:to_json).with(:indent => "\t")
|
18
|
+
object.should_receive(:to_json).with(:indent => "\t")
|
23
19
|
MultiJson.dump(object, :indent => "\t")
|
24
20
|
end
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
28
24
|
describe '.load' do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
MultiJson.load('"foo"', :quirks_mode => true)
|
33
|
-
end
|
25
|
+
it 'passes :quirks_mode option' do
|
26
|
+
::JSON.should_receive(:parse).with('[123]', {:quirks_mode => false, :create_additions => false})
|
27
|
+
MultiJson.load('[123]', :quirks_mode => false)
|
34
28
|
end
|
35
29
|
end
|
36
30
|
end
|
data/spec/multi_json_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'adapter_shared_example'
|
3
3
|
require 'json_common_shared_example'
|
4
|
+
require 'has_options'
|
4
5
|
require 'stringio'
|
5
6
|
|
6
7
|
describe 'MultiJson' do
|
@@ -34,8 +35,9 @@ describe 'MultiJson' do
|
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'defaults to ok_json if no other json implementions are available' do
|
37
|
-
|
38
|
-
|
38
|
+
silence_warnings do
|
39
|
+
expect(MultiJson.default_adapter).to eq :ok_json
|
40
|
+
end
|
39
41
|
end
|
40
42
|
|
41
43
|
it 'prints a warning' do
|
@@ -48,47 +50,50 @@ describe 'MultiJson' do
|
|
48
50
|
# Clear cache variable already set by previous tests
|
49
51
|
MultiJson.send(:remove_instance_variable, :@adapter)
|
50
52
|
unless jruby?
|
51
|
-
|
52
|
-
expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::Oj'
|
53
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::Oj
|
53
54
|
else
|
54
|
-
|
55
|
-
expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::JsonGem'
|
55
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'looks for adapter even if @adapter variable is nil' do
|
60
60
|
MultiJson.send(:instance_variable_set, :@adapter, nil)
|
61
61
|
MultiJson.should_receive(:default_adapter).and_return(:ok_json)
|
62
|
-
expect(MultiJson.adapter
|
62
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::OkJson
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'is settable via a symbol' do
|
66
66
|
MultiJson.use :json_gem
|
67
|
-
expect(MultiJson.adapter
|
67
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'is settable via a class' do
|
71
|
-
|
72
|
-
|
71
|
+
adapter = Class.new
|
72
|
+
MultiJson.use adapter
|
73
|
+
expect(MultiJson.adapter).to eq adapter
|
73
74
|
end
|
74
75
|
|
75
76
|
it 'is settable via a module' do
|
76
|
-
|
77
|
-
|
77
|
+
adapter = Module.new
|
78
|
+
MultiJson.use adapter
|
79
|
+
expect(MultiJson.adapter).to eq adapter
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'throws ArgumentError on bad input' do
|
83
|
+
expect{ MultiJson.use 'bad adapter' }.to raise_error(ArgumentError)
|
78
84
|
end
|
79
85
|
|
80
86
|
context 'using one-shot parser' do
|
81
87
|
before do
|
82
|
-
|
83
|
-
MultiJson::Adapters::JsonPure.should_receive(:
|
84
|
-
MultiJson::Adapters::JsonPure.should_receive(:load).exactly(1).times.and_return('load_something')
|
88
|
+
MultiJson::Adapters::JsonPure.should_receive(:dump).once.and_return('dump_something')
|
89
|
+
MultiJson::Adapters::JsonPure.should_receive(:load).once.and_return('load_something')
|
85
90
|
end
|
86
91
|
|
87
92
|
it 'should use the defined parser just for the call' do
|
88
93
|
MultiJson.use :json_gem
|
89
94
|
expect(MultiJson.dump('', :adapter => :json_pure)).to eq 'dump_something'
|
90
95
|
expect(MultiJson.load('', :adapter => :json_pure)).to eq 'load_something'
|
91
|
-
expect(MultiJson.adapter
|
96
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
|
92
97
|
end
|
93
98
|
end
|
94
99
|
end
|
@@ -97,11 +102,11 @@ describe 'MultiJson' do
|
|
97
102
|
MultiJson.use :ok_json
|
98
103
|
MultiJson.with_adapter(:json_pure) do
|
99
104
|
MultiJson.with_engine(:json_gem) do
|
100
|
-
expect(MultiJson.adapter
|
105
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
|
101
106
|
end
|
102
|
-
expect(MultiJson.adapter
|
107
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonPure
|
103
108
|
end
|
104
|
-
expect(MultiJson.adapter
|
109
|
+
expect(MultiJson.adapter).to eq MultiJson::Adapters::OkJson
|
105
110
|
end
|
106
111
|
|
107
112
|
it 'JSON gem does not create symbols on parse' do
|
@@ -126,18 +131,28 @@ describe 'MultiJson' do
|
|
126
131
|
end
|
127
132
|
end
|
128
133
|
|
129
|
-
|
130
|
-
MultiJson.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
134
|
+
describe 'default options' do
|
135
|
+
after(:all){ MultiJson.load_options = MultiJson.dump_options = nil }
|
136
|
+
|
137
|
+
it 'is deprecated' do
|
138
|
+
Kernel.should_receive(:warn).with(/deprecated/i)
|
139
|
+
silence_warnings{ MultiJson.default_options = {:foo => 'bar'} }
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'sets both load and dump options' do
|
143
|
+
MultiJson.should_receive(:dump_options=).with(:foo => 'bar')
|
144
|
+
MultiJson.should_receive(:load_options=).with(:foo => 'bar')
|
145
|
+
silence_warnings{ MultiJson.default_options = {:foo => 'bar'} }
|
146
|
+
end
|
135
147
|
end
|
136
148
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
next if jruby? && (
|
149
|
+
it_behaves_like 'has options', MultiJson
|
150
|
+
|
151
|
+
%w(gson jrjackson json_gem json_pure nsjsonserialization oj ok_json yajl).each do |adapter|
|
152
|
+
next if !jruby? && %w(gson jrjackson).include?(adapter)
|
153
|
+
next if !macruby? && adapter == 'nsjsonserialization'
|
154
|
+
next if jruby? && %w(oj yajl).include?(adapter)
|
155
|
+
|
141
156
|
context adapter do
|
142
157
|
it_behaves_like 'an adapter', adapter
|
143
158
|
end
|
@@ -148,4 +163,4 @@ describe 'MultiJson' do
|
|
148
163
|
it_behaves_like 'JSON-like adapter', adapter
|
149
164
|
end
|
150
165
|
end
|
151
|
-
end
|
166
|
+
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.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -39,7 +39,7 @@ cert_chain:
|
|
39
39
|
U0xxV3ZRUnNCbHlwSGZoczZKSnVMbHlaUEdoVTNSL3YKU2YzbFZLcEJDV2dS
|
40
40
|
cEdUdnk0NVhWcEIrNTl5MzNQSm1FdVExUFRFT1l2UXlhbzlVS01BQWFBTi83
|
41
41
|
cVdRdGpsMApobHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
42
|
-
date: 2013-
|
42
|
+
date: 2013-03-16 00:00:00.000000000 Z
|
43
43
|
dependencies:
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: bundler
|
@@ -79,10 +79,13 @@ files:
|
|
79
79
|
- .rspec
|
80
80
|
- .travis.yml
|
81
81
|
- spec/adapter_shared_example.rb
|
82
|
+
- spec/has_options.rb
|
82
83
|
- spec/helper.rb
|
83
84
|
- spec/json_common_shared_example.rb
|
84
85
|
- spec/multi_json_spec.rb
|
86
|
+
- lib/multi_json/adapter.rb
|
85
87
|
- lib/multi_json/adapters/gson.rb
|
88
|
+
- lib/multi_json/adapters/jrjackson.rb
|
86
89
|
- lib/multi_json/adapters/json_common.rb
|
87
90
|
- lib/multi_json/adapters/json_gem.rb
|
88
91
|
- lib/multi_json/adapters/json_pure.rb
|
@@ -90,6 +93,8 @@ files:
|
|
90
93
|
- lib/multi_json/adapters/oj.rb
|
91
94
|
- lib/multi_json/adapters/ok_json.rb
|
92
95
|
- lib/multi_json/adapters/yajl.rb
|
96
|
+
- lib/multi_json/convertible_hash_keys.rb
|
97
|
+
- lib/multi_json/options.rb
|
93
98
|
- lib/multi_json/vendor/okjson.rb
|
94
99
|
- lib/multi_json/version.rb
|
95
100
|
- lib/multi_json.rb
|
@@ -114,12 +119,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
119
|
version: 1.3.6
|
115
120
|
requirements: []
|
116
121
|
rubyforge_project:
|
117
|
-
rubygems_version: 1.8.
|
122
|
+
rubygems_version: 1.8.25
|
118
123
|
signing_key:
|
119
124
|
specification_version: 3
|
120
125
|
summary: A gem to provide swappable JSON backends.
|
121
126
|
test_files:
|
122
127
|
- spec/adapter_shared_example.rb
|
128
|
+
- spec/has_options.rb
|
123
129
|
- spec/helper.rb
|
124
130
|
- spec/json_common_shared_example.rb
|
125
131
|
- spec/multi_json_spec.rb
|
metadata.gz.sig
CHANGED
Binary file
|