Ruby on Rails Advanced JSON Serialization
Solution 1
You hint at the solution in your question. You most likely want to build up a hash to render to JSON. The preferred way of doing this now is by providing an implementation for the as_json method. as_json provides a formal means of customizing to_json output by building up a hash containing the data you wish to encode.
A more thorough treatment of how as_json and to_json interact can be found on Jonathan Julian's weblog.
Solution 2
You should be able to nest the :include
, :except
, etc. like so:
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}...
If that doesn't work, make it an object (e.g. an OpenStruct) instead of a hash.
-- Markus
Solution 3
to_json has a :method option that includes the result of any method you name, you could define a method on that model that returns the additional data you want in your JSON.
Solution 4
(Please accept an answer)
I think that the link that nirvdrum gave holds your answer. I only answer because nobody has mentioned encode_json
.
In your case you should only be dealing with as_json
. Either by building a hash (with various calls to as_json
) and sending that to render :json => ...
(without the call to to_json
) or by simply implementing as_json
on your model and letting rails do all the work. (But I suspect you'll need the former.)
If you really need some fancy js in your rendered response then you can implement encode_json
in your classes (again, not to_json
). For example:
class JsEmptyClosure
def encode_json(*args)
"jQuery[\"noop\"] || function(){}"
end
def as_json(*args) self end
end
This will now respond to to_json
with valid js (but note it's not actually json).
Admin
Updated on July 09, 2022Comments
-
Admin almost 2 years
I'm looking to render an index of all articles along with a full article via JSON in my rails app, but I'm having a little trouble figuring out how to do it.
Here is my controller now:
if params[:id] @article = Article.find(params[:id]) else @article = Article.published.not_draft.by_recent.first end respond_to do |format| format.js { render :json => @article.to_json( :except => [ :created_at, :updated_at, :draft, :id, :publish ], :include => { :comments => { :only => [:body] } }), :callback => params[:callback]} end
What I'd like to do in the response is add an index of all articles, like so:
@index = Article.find(:all, :select => 'id, title')
The only way I've been able to do it, is put both the index and article into a hash or array and then put that to JSON.
@response = { :item => @article, :index => @index }
Full code with both:
@index = Article.find(:all, :select => 'id, title') if params[:id] @article = Article.find(params[:id]) else @article = Article.published.not_draft.by_recent.first end @response = { :item => @article, :index => @index } respond_to do |format| format.js { render :json => @response.to_json(), :callback => params[:callback]} end
This would be fine, except now I cannot specify
:include
or:except
and get it to render properly.