Dave Perrett

Excluding Fields From Rails Json and Xml Output

json, quickie, rails, rest, ruby, xml

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

1
2
3
4
5
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 :

1
2
3
4
5
6
7
8
<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 :

1
2
3
4
5
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 :

1
2
3
4
5
6
<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 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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