multi_json 1.6.1 → 1.7.0

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.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