-
Notifications
You must be signed in to change notification settings - Fork 129
/
Copy pathmulti_json.rb
166 lines (140 loc) · 4.14 KB
/
multi_json.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
require "multi_json/options"
require "multi_json/version"
require "multi_json/adapter_error"
require "multi_json/parse_error"
require "multi_json/options_cache"
module MultiJson
include Options
extend self
def default_options=(value)
Kernel.warn "MultiJson.default_options setter is deprecated\nUse MultiJson.load_options and MultiJson.dump_options instead"
self.load_options = self.dump_options = value
end
def default_options
Kernel.warn "MultiJson.default_options is deprecated\nUse MultiJson.load_options or MultiJson.dump_options instead"
load_options
end
%w[cached_options reset_cached_options!].each do |method_name|
define_method method_name do |*|
Kernel.warn "MultiJson.#{method_name} method is deprecated and no longer used."
end
end
ALIASES = {"jrjackson" => "jr_jackson"}.freeze
REQUIREMENT_MAP = {
oj: "oj",
yajl: "yajl",
jr_jackson: "jrjackson",
json_gem: "json/ext",
gson: "gson",
json_pure: "json/pure"
}
# The default adapter based on what you currently
# have loaded and installed.
def default_adapter
adapter = loaded_adapter || installable_adapter
return adapter if adapter
Kernel.warn "[WARNING] MultiJson is using the default adapter (ok_json). We recommend loading a different JSON library to improve performance."
:ok_json
end
alias_method :default_engine, :default_adapter
# Get the current adapter class.
def adapter
return @adapter if defined?(@adapter) && @adapter
use nil # load default adapter
@adapter
end
alias_method :engine, :adapter
# Set the JSON parser utilizing a symbol, string, or class.
# Supported by default are:
#
# * <tt>:oj</tt>
# * <tt>:json_gem</tt>
# * <tt>:json_pure</tt>
# * <tt>:ok_json</tt>
# * <tt>:yajl</tt>
# * <tt>:gson</tt> (JRuby only)
# * <tt>:jr_jackson</tt> (JRuby only)
def use(new_adapter)
@adapter = load_adapter(new_adapter)
ensure
OptionsCache.reset
end
alias_method :adapter=, :use
alias_method :engine=, :use
def load_adapter(new_adapter)
case new_adapter
when String, Symbol
load_adapter_from_string_name new_adapter.to_s
when NilClass, FalseClass
load_adapter default_adapter
when Class, Module
new_adapter
else
raise ::LoadError, new_adapter
end
rescue ::LoadError => e
raise AdapterError.build(e)
end
# Decode a JSON string into Ruby.
#
# <b>Options</b>
#
# <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
# <tt>:adapter</tt> :: If set, the selected adapter will be used for this call.
def load(string, options = {})
adapter = current_adapter(options)
begin
adapter.load(string, options)
rescue adapter::ParseError => e
raise ParseError.build(e, string)
end
end
alias_method :decode, :load
def current_adapter(options = {})
if (new_adapter = options[:adapter])
load_adapter(new_adapter)
else
adapter
end
end
# Encodes a Ruby object as JSON.
def dump(object, options = {})
current_adapter(options).dump(object, options)
end
alias_method :encode, :dump
# Executes passed block using specified adapter.
def with_adapter(new_adapter)
old_adapter = adapter
self.adapter = new_adapter
yield
ensure
self.adapter = old_adapter
end
alias_method :with_engine, :with_adapter
private
# Checks for already loaded adapters and returns the first match
def loaded_adapter
return :oj if defined?(::Oj)
return :yajl if defined?(::Yajl)
return :jr_jackson if defined?(::JrJackson)
return :json_gem if defined?(::JSON::Ext::Parser)
return :gson if defined?(::Gson)
nil
end
# Attempts to load and return the first installable adapter
def installable_adapter
REQUIREMENT_MAP.each do |adapter, library|
require library
return adapter
rescue ::LoadError
next
end
nil
end
def load_adapter_from_string_name(name)
name = ALIASES.fetch(name, name)
require "multi_json/adapters/#{name.downcase}"
klass_name = name.to_s.split("_").map(&:capitalize) * ""
MultiJson::Adapters.const_get(klass_name)
end
end