Get updates

Scott Q&A: How to Customize Rails to_json output?

Rails has a bunch of JavaScript helpers, but once you move beyond those and want to write your own JavaScript code for your application, you may find yourself dealing with some JSON produced on the server-side.

By default, the to_json method in Rails is probably a lot more verbose than most people want. I’ll share a few tips on how to tame it.

Question: How can I slim down the output of to_json in Rails?

Answer: It depends a little on the details of what you want, but this is what worked for me.

The other day I was working on a controller action with some code like this:

respond_to do |format|
  format.js { render :json => @items.to_json }

@items is a collection of Item model objects. The response to my Ajax request came out like this:

[{"item": {"position": 1, "created_at": "2009-04-19T14:36:11Z", "updated_at": "2009-04-19T14:36:11Z", "id": 88, "user_id": 1, "parent_id": 87, "content": "child"}}]

Rather excessive. Until I learned about the :only option for to_json (see the last line here):

  format.js { render :json => @items.to_json(:only => [:id, :content]) }
#[{"item": {"id": 88, "content": "child"}}]

Definitely better. No need to worry about all of those extra attributes, which are useful on the server-side but nothing the client will use. Some things the client has no business knowing, like perhaps the user_id. Similarly, the :except option acts to blacklist attributes, if you want an alternative to the whitelist of :only.

Looking at the newer output again, it starts with an array. That’s sensible, @items is a collection and could have more than one element (though just one here, to keep this example clean). Then there’s an object with a property matching the model object’s class (‘item’). Technically you could use this to perform different operations on based on the type of objects in the response.

Realistically, in my situation I decided that only one type of object should come back in response to my requests. Thus to access the object’s attributes requires hardcoding the class in JavaScript, or iterating over the containing objects to get their class, neither of which are as simple as I want.

Instead, there’s a config flag which allows you to turn this behavior off, in config/initializers/new_rails_defaults.rb:

ActiveRecord::Base.include_root_in_json = false
#[{"id": 88, "content": "child"}]

Excellent! Now I can iterate over my collection (Prototype’s Enumerable methods are a great choice) easily, knowing my objects are accessible without having to use a class key, and without the extra fat of a bunch of unnecessary attributes.

One Response to “Q&A: How to Customize Rails to_json output?”

  1. Hitesh Manchanda Says:

    Really of great help.

Leave a Reply