aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext/object
diff options
context:
space:
mode:
authorGodfrey Chan <godfreykfc@gmail.com>2013-11-12 01:57:21 -0800
committerGodfrey Chan <godfreykfc@gmail.com>2013-11-14 15:46:43 -0800
commit0f33d70e89991711ff8b3dde134a61f4a5a0ec06 (patch)
treedf93bc8ab410476175fd07f61105ff09ad86084a /activesupport/lib/active_support/core_ext/object
parent07996ebc50f5906dbecc481ac83ed2adefc9ec6e (diff)
downloadrails-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/active_support/core_ext/object')
-rw-r--r--activesupport/lib/active_support/core_ext/object/json.rb24
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