A fast, dumb JSON serialization approach for Rails

Nowadays there are some great gems to generate your JSON responses. ActiveModel::Serializers (my preferred solution), Jbuilder and RABL (bit obscure syntax and some pitfalls).

At the moment I have to build an API which is not restful and the responses contain hundreds to thousands of serialized objects. I tried all of the above gems and realized that it's quite painful to build highly customized data structures that are not tightly coupled to the objects. Don't get me wrong - it can be achieved, but the complexity of the syntax and hacks just didn't feel right.

Here is a simple approach, that fitted really nice into my scenario:
I built a service object for the JSON serialization.

# note: this data structure is very easy and could be easily done with the help of a gem. just chosen for the sake of simplicity!

class Api::V1::MySpecialJsonService  
  # pass in the needed params from the controller here
  def initialize(params)
    @foo = params[:foo]
  end

  def as_json(options={})
    {
      series: set_series,
      people: set_people,
      categoryTags: []
    }
  end

  private

  def set_series
    series = []
    Franchise.all.each do |franchise|
      series << {
        id:            franchise.id.to_s,
        urlKey:        franchise.identifier,
        type:          'series',
        original_name: franchise.original_name
      }
    end
    series
  end

  def set_people
    people = []
    collection = @foo ? People.all : People.some_scope
    collection.each do |person|
      people << {
        id:            person.id.to_s,
        urlKey:        person.id.to_s,
        type:          'person',
        original_name: person.name
      }
    end
    people
  end
end  

And in the controller you just have to instantiate the service object and pass it to the render method. It will call as_json on the service object automatically.

# some controller

def index  
  response = Api::V1::MySpecialJsonService.new(params)
  render json: response
end  

In terms of speed this approach is also faster as using a gem - it's just pure Ruby and there is no other layer involved.

The service object can be tested perfectly via RSpec, integrations tests involving routing and controller can be done via Rspec request specs. A cool blog post on request specs from Matthew Lehner can be found here.

My advise:

Use ActiveModel::Serializers at RESTful API's. Use serialization service objects for highly customizable structures.

You can also use a gem and the service object approach together and choose per method which one fits better!