Skip to content
Browse files

renderer calls object.to_json when rendering :json => object [#5655 s…


Signed-off-by: José Valim <>
  • Loading branch information...
1 parent 4966b91 commit 72f37bd8bc5b3beb1e8a2d1ac2de2c045cd0cfd2 @dcrec1 dcrec1 committed with josevalim
2  actionpack/lib/action_controller/metal/renderers.rb
@@ -71,7 +71,7 @@ def self._write_render_options
add :json do |json, options|
- json = ActiveSupport::JSON.encode(json, options) unless json.respond_to?(:to_str)
+ json = json.to_json(options) unless json.respond_to?(:to_str)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
self.content_type ||= Mime::JSON
self.response_body = json
13 actionpack/test/controller/render_json_test.rb
@@ -9,6 +9,10 @@ def as_json(options={})
hash.except!(*options[:except]) if options[:except]
+ def to_json(options = {})
+ super :except => [:c, :e]
+ end
class TestController < ActionController::Base
@@ -49,6 +53,10 @@ def render_json_with_render_to_string
def render_json_with_extra_options
render :json =>, :except => [:c, :e]
+ def render_json_without_options
+ render :json =>
+ end
tests TestController
@@ -109,4 +117,9 @@ def test_render_json_forwards_extra_options
assert_equal '{"a":"b"}', @response.body
assert_equal 'application/json', @response.content_type
+ def test_render_json_calls_to_json_from_object
+ get :render_json_without_options
+ assert_equal '{"a":"b"}', @response.body
+ end

3 comments on commit 72f37bd


I thought we were trying to get rid of to_json entirely? (or as much as possible at least)


what is the problem with to_json?


The JSON gem, ActiveSupport and yajl-ruby's JSON gem compatibility API all override that method. If someone includes 'yajl/json_gem' after ActiveSupport has been loaded, the above code will work but not the way the caller expects since the options hash for ActiveSupport's version of to_json is completely different than that of the one in yajl-ruby's JSON gem compatibility API.

I was under the assumption as_json was added to help get around this by allowing one to provide a JSON encodable version of their object using primitives that are directly mappable to JSON from Ruby, and the other way around. Then to actually encode the object, it would be passed through ActiveSupport::JSON.encode which has no chance of being overridden elsewhere and as such would have consistent behavior everywhere.

Rails actually has a hack for this from long-standing issues in the past with the JSON gem and ActiveSupport both overriding to_json.

Please sign in to comment.
Something went wrong with that request. Please try again.