Excluding fields from rails json and xml output

Filed under json, quickie, rails, rest, ruby, and xml.

Rails has a very handy ‘respond_to’ feature to render your pages in different formats :

respond_to do |format|
  format.json { render :json => @user }
  format.xml  { render :xml => @user }
  format.html      
end

However, by default it outputs every field in the model, which exposes some data (encrypted-password and password-salt) that I’d rather keep to myself :

<user> 
  <encrypted-password>$2a$10$a2K.PXEXpgpWH6MMLD/AFe84mjB4u3ZNf4MYTPten42LkPpjd.wZm</encrypted-password> 
  <created-at type="datetime">2010-10-02T00:12:43Z</created-at> 
  <updated-at type="datetime">2010-10-03T03:28:27Z</updated-at>  
  <id type="integer">12</id> 
  <password-salt>$2a$10$a2K.PXEXpgpWH6MMLD/AFe</password-salt> 
  <email>mail@recursive-design.com</email> 
</user>

Luckily, you can disable specific fields using the except option :

respond_to do |format|
  format.json { render :json => @user, :except=>  [:encrypted_password, :password_salt] }
  format.xml  { render :xml => @user, :except=>  [:encrypted_password, :password_salt] }
  format.html      
end

… which removes the offending fields from output :

<user> 
  <created-at type="datetime">2010-10-02T00:12:43Z</created-at> 
  <updated-at type="datetime">2010-10-03T03:28:27Z</updated-at>  
  <id type="integer">12</id> 
  <email>dave@recurser.com</email> 
</user>

If you find yourself doing this in a lot of different places, it may be easier to filter these options at the model level, by over-riding the ‘to_json’ and ‘to_xml’ methods :

class User < ActiveRecord::Base
  
  ...
   
   # Exclude password info from xml output.
   def to_xml(options={})
     options[:except] ||= [:encrypted_password, :password_salt]
     super(options)
   end
   
   # Exclude password info from json output.
   def to_json(options={})
     options[:except] ||= [:encrypted_password, :password_salt]
     super(options)
   end
  
  ...
  
end

If you enjoyed this post, please follow us on twitter or subscribe to our feed!