Recursive custom to_json in Ruby for arrays of objects or nested objects

Let’s say we want to customize the json template for an object:

class User
  def to_json
    super(:except => [:password, :password_salt, :encrypted_password,
      :last_sign_in_ip, :updated_at, :current_sign_in_ip,
      :remember_token, :reset_password_token, :remember_created_at])
  end
end

Apparently this is fixed in Ruby 1.9 but for now only converting an object directly to custom json works:

@user = User.first
@user.to_json
# works fine

Cool but we want that to work for arrays:

@users = User.all
@users.to_json
# prints all attributes (does not hit our custom to_json)

And we also want custom responses in our APIs:

@users = User.all
data = {}
data[:results] = @users
data[:count] = @users.length
data.to_json
# prints all attributes (does not hit our custom to_json)

To fix this override as_json and use ActiveSupport’s encoding method. Don’t override to_json:

class User
def as_json(options)
    super(:except => [:password, :password_salt, :encrypted_password,
      :last_sign_in_ip, :updated_at, :current_sign_in_ip,
      :remember_token, :reset_password_token, :remember_created_at])
  end
end
 
...
@users = User.order_by("last_name")
      if @users
        data = {}
        data[:results] = @users
        res = data.as_json
        ActiveSupport::JSON.encode(res)
...
No TweetBacks yet. (Be the first to Tweet this post)
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • MySpace
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

If you enjoyed this post, make sure you subscribe to my RSS feed!

This entry was posted in Software and tagged , , , , , . Bookmark the permalink. Both comments and trackbacks are currently closed.

2 Comments

  1. Posted March 25, 2011 at 5:47 pm | Permalink

    as_json is the way to go! I spent some time investigating this last year, see my post for more details of how to_json and as_json interact in Rails.

  2. Nick B
    Posted September 11, 2012 at 5:49 am | Permalink

    Thanks. This post saved my day.