Responding with JSON in Rails
When building a RESTful API in Rails, there are many different options and gems you can use to format your JSON responses. This isn't a post about how to build an API, but rather about some of the different popular options on how to define and structure JSON.
RABL
RABL is a DSL for generating both JSON and XML. In my mind it has a similar feel to Jbuilder, which I'll discuss below. It's works by creating a view with the extension .rabl, and defining which attributes, nodes, and relations you wish to include in the JSON response. Here's an example taken from their GitHub README.
# app/views/posts/index.rablcollection @postsattributes :id, :title, :subjectchild(:user) { attributes :full_name }node(:read) { |post| post.read_by?(@user) }
Active Model Serializer
Active Model Serializer is a great way to build JSON responses using an object oriented approach. The objects have a very similar feel to how your ActiveModel object is set up in terms of attributes and relationships. It also allows you to choose your adapter-to decide what type of JSON structure is produced-or to build your own. Popular supported formats are JSON-API and JSON-HAL.
class PostSerializer < ActiveModel::Serializerattributes :title, :bodyhas_many :commentsurl :postend
Jbuilder
Jbuilder provides a very similar DSL to RABL. Jbuilder is included with Rails, so it is used quite a bit. Rails Casts has a free episode which goes into greater detail about Jbuilder. It's very easy to use and provides a lot of flexibility in defining exactly what attributes are included in and how the response is formatted and nested.
# app/views/message/show.json.jbuilderjson.content format_content(@message.content)json.(@message, :created_at, :updated_at)json.author dojson.name @message.creator.name.familiarjson.email_address @message.creator.email_address_with_namejson.url url_for(@message.creator, format: :json)end
Grape Entity
Grape Entity was extracted from Grape, which is a popular gem used for building RESTful APIs. Similarly to RABL and Jbuilder, it provides a DSL for defining entities which are the structure of your JSON response.
module APImodule Entitiesclass Status < Grape::Entityexpose :user_nameexpose :text, documentation: { type: "String", desc: "Status update text." }expose :ip, if: { type: :full }expose :user_type, :user_id, if: lambda { |status, options| status.user.public? }expose :contact_info doexpose :phoneexpose :address, using: API::Addressendendendend
ROAR
ROAR allows you to build presenter classes to represent your data. It comes with support for JSON, JSON-HAL, JSON-API, and XML.
require 'roar/json'module SongRepresenterinclude Roar::JSONproperty :titleend
ActiveModel or Hash
This may seem like a strange thing to point out, but for very simple cases, you can simply call the to_json method on either an ActiveModel object or a native Ruby Hash.
# Using an @organization modelrespond_to do |format|format.json dorender json: @organization.to_jsonendend
# Using a plain Ruby Hashrespond_to do |format|format.json dorender json: {name: @user.name,email: @user.email}.to_jsonendend
JSON Specifications
For more information on some of the different JSON structures, please refer to the links below. I will be writing an article at a later time specifically about how these options differ from one another.