diff options
author | Godfrey Chan <godfreykfc@gmail.com> | 2013-11-12 01:57:21 -0800 |
---|---|---|
committer | Godfrey Chan <godfreykfc@gmail.com> | 2013-11-14 15:46:43 -0800 |
commit | 0f33d70e89991711ff8b3dde134a61f4a5a0ec06 (patch) | |
tree | df93bc8ab410476175fd07f61105ff09ad86084a /activesupport/lib | |
parent | 07996ebc50f5906dbecc481ac83ed2adefc9ec6e (diff) | |
download | rails-0f33d70e89991711ff8b3dde134a61f4a5a0ec06.tar.gz rails-0f33d70e89991711ff8b3dde134a61f4a5a0ec06.tar.bz2 rails-0f33d70e89991711ff8b3dde134a61f4a5a0ec06.zip |
Improved compatibility with the stdlib JSON gem.
Previously, calling `::JSON.{generate,dump}` sometimes causes
unexpected failures such as intridea/multi_json#86.
`::JSON.{generate,dump}` now bypasses the ActiveSupport JSON encoder
completely and yields the same result with or without ActiveSupport.
This means that it will **not** call `as_json` and will ignore any
options that the JSON gem does not natively understand. To invoke
ActiveSupport's JSON encoder instead, use `obj.to_json(options)` or
`ActiveSupport::JSON.encode(obj, options)`.
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/active_support/core_ext/object/json.rb | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb index 898c3f4307..5157b0402f 100644 --- a/activesupport/lib/active_support/core_ext/object/json.rb +++ b/activesupport/lib/active_support/core_ext/object/json.rb @@ -9,18 +9,36 @@ require 'time' require 'active_support/core_ext/time/conversions' require 'active_support/core_ext/date_time/conversions' require 'active_support/core_ext/date/conversions' +require 'active_support/core_ext/module/aliasing' # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting # their default behavior. That said, we need to define the basic to_json method in all of them, # otherwise they will always use to_json gem implementation, which is backwards incompatible in # several cases (for instance, the JSON implementation for Hash does not work) with inheritance # and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json. +# +# On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the +# JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always +# passes a ::JSON::State object as the only argument to to_json, we can detect that and forward the +# calls to the original to_json method. +# +# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is +# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply +# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump} +# should give exactly the same results with or without active support. [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass| klass.class_eval do - # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def to_json(options = nil) - ActiveSupport::JSON.encode(self, options) + def to_json_with_active_support_encoder(options = nil) + if options.is_a?(::JSON::State) + # Called from JSON.{generate,dump}, forward it to JSON gem's to_json + self.to_json_without_active_support_encoder(options) + else + # to_json is being invoked directly, use ActiveSupport's encoder + ActiveSupport::JSON.encode(self, options) + end end + + alias_method_chain :to_json, :active_support_encoder end end |