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 CHANGED
Binary file
@@ -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
@@ -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
- @default_options = {}
16
- attr_accessor :default_options
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
- # :nodoc:
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
- # :nodoc:
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 :adapter= :use
76
- # :nodoc:
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 "Did not recognize your adapter specification. Please specify either a symbol or a class."
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 engine will be used just for the call.
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
- # :nodoc:
108
- alias :decode :load
118
+ alias decode load
109
119
 
110
- def current_adapter(options)
111
- if new_adapter = (options || {}).delete(: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 = default_options.merge(options)
121
- adapter = current_adapter(options)
122
- adapter.dump(object, options)
130
+ current_adapter(options).dump(object, options)
123
131
  end
124
- # :nodoc:
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
- # :nodoc:
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
- module Gson
7
- extend self
8
-
7
+ class Gson < Adapter
9
8
  ParseError = ::Gson::DecodeError
10
9
 
11
- def load(string, options={}) #:nodoc:
10
+ def load(string, options={})
12
11
  ::Gson::Decoder.new(options).decode(string)
13
12
  end
14
13
 
15
- def dump(object, options={}) #:nodoc:
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
- module JsonCommon
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
- protected
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
- def process_dump_options!(options={})
22
- process_options!({}, options) do |opts|
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 process_options!(default_options, options)
28
- return default_options if options.empty?
29
- yield default_options
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
@@ -4,9 +4,8 @@ require 'multi_json/adapters/json_common'
4
4
  module MultiJson
5
5
  module Adapters
6
6
  # Use the JSON gem to dump/load.
7
- module JsonGem
7
+ class JsonGem < JsonCommon
8
8
  ParseError = ::JSON::ParserError
9
- extend JsonCommon
10
9
  end
11
10
  end
12
11
  end
@@ -4,9 +4,8 @@ require 'multi_json/adapters/json_common'
4
4
  module MultiJson
5
5
  module Adapters
6
6
  # Use JSON pure to dump/load.
7
- module JsonPure
7
+ class JsonPure < JsonCommon
8
8
  ParseError = ::JSON::ParserError
9
- extend JsonCommon
10
9
  end
11
10
  end
12
11
  end
@@ -3,8 +3,7 @@ require 'multi_json/adapters/ok_json'
3
3
 
4
4
  module MultiJson
5
5
  module Adapters
6
- module Nsjsonserialization
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
- module Oj
7
- extend self
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={}) #:nodoc:
18
- options.merge!(:symbol_keys => options[:symbolize_keys])
19
- options[:mode] = :strict
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={}) #:nodoc:
22
+ def dump(object, options={})
24
23
  options.merge!(:indent => 2) if options[:pretty]
25
- ::Oj.dump(object, DEFAULT_OPTIONS.merge(options))
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
- module OkJson
6
- extend self
7
-
7
+ class OkJson < Adapter
8
+ include ConvertibleHashKeys
8
9
  ParseError = ::MultiJson::OkJson::Error
9
10
 
10
- def load(string, options={}) #:nodoc:
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={}) #:nodoc:
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
- module Yajl
7
- extend self
8
-
7
+ class Yajl < Adapter
9
8
  ParseError = ::Yajl::ParseError
10
9
 
11
- def load(string, options={}) #:nodoc:
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={}) #:nodoc:
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
@@ -1,3 +1,3 @@
1
1
  module MultiJson
2
- VERSION = "1.6.1" unless defined?(MultiJson::VERSION)
2
+ VERSION = '1.7.0' unless defined?(MultiJson::VERSION)
3
3
  end
@@ -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 == 'gson'
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
@@ -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
@@ -1,9 +1,11 @@
1
- if !ENV['CI'] && defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby'
2
- require 'simplecov'
3
- SimpleCov.start do
4
- add_filter 'vendor'
5
- end
6
- end
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 do
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).and_return('["foo"]')
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").and_return('["foo"]')
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
- describe 'with :quirks_mode option' do
30
- it 'passes it on load' do
31
- ::JSON.should_receive(:parse).with('["foo"]', {:quirks_mode => true, :create_additions => false}).and_return(['foo'])
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
@@ -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
- Kernel.stub(:warn)
38
- expect(MultiJson.default_adapter).to eq :ok_json
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
- require 'oj'
52
- expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::Oj'
53
+ expect(MultiJson.adapter).to eq MultiJson::Adapters::Oj
53
54
  else
54
- require 'json'
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.name).to eq 'MultiJson::Adapters::OkJson'
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.name).to eq 'MultiJson::Adapters::JsonGem'
67
+ expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
68
68
  end
69
69
 
70
70
  it 'is settable via a class' do
71
- MultiJson.use MockDecoder
72
- expect(MultiJson.adapter.name).to eq 'MockDecoder'
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
- MultiJson.use MockModuleDecoder
77
- expect(MultiJson.adapter.name).to eq 'MockModuleDecoder'
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
- require 'multi_json/adapters/json_pure'
83
- MultiJson::Adapters::JsonPure.should_receive(:dump).exactly(1).times.and_return('dump_something')
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.name).to eq 'MultiJson::Adapters::JsonGem'
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.name).to eq 'MultiJson::Adapters::JsonGem'
105
+ expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonGem
101
106
  end
102
- expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::JsonPure'
107
+ expect(MultiJson.adapter).to eq MultiJson::Adapters::JsonPure
103
108
  end
104
- expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::OkJson'
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
- it 'has default_options setter' do
130
- MultiJson.use MockDecoder
131
- MockDecoder.should_receive(:dump).with('123', :foo => 'lol', :bar => 'bar', :fizz => 'buzz')
132
- MultiJson.default_options = { :foo => 'foo', :bar => 'bar' }
133
- MultiJson.dump('123', :fizz => 'buzz', :foo => 'lol')
134
- MultiJson.default_options = {}
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
- %w(gson json_gem json_pure nsjsonserialization oj ok_json yajl).each do |adapter|
138
- next if adapter == 'gson' && !jruby?
139
- next if adapter == 'nsjsonserialization' && !macruby?
140
- next if jruby? && (adapter == 'oj' || adapter == 'yajl')
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.6.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-02-14 00:00:00.000000000 Z
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.23
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