JsonDumper

Serialize Ruby into JSON. Cleaner. Faster.

This gem is intended to

  • help serialize Ruby objects and ActiveRecord objects into json
  • help organize your code
  • solve N+1 query problem

Installation

Add this line to your application's Gemfile:

gem 'json_dumper'

And then execute:

$ bundle

Or install it yourself as:

$ gem install json_dumper

Usage

Let's say you want to serialize Human object, which has many Cars. First define a class that is going to serialize Human:

class HumanJson < JsonDumper::Base
  def preview
    {
      id: id,
      first_name: first_name,
      last_name: last_name,
      born_at: created_at.strftime('%m/%d/%Y')
    }
  end
end

you can call it like that:

john = Human.create(
  first_name: 'John',
  last_name: 'Doe',
  created_at: 20.years.ago
)

json = HumanJson.preview(john)
json == {
  id: 1,
  first_name: 'John',
  last_name: 'Doe',
  born_at: '09/19/1997'
}

Whenever you invoke a method on a JsonDumper::Base instance and it is missing a similar method is invoked on the object you passed to the serializer. For example in the snippet above a method id is going to be called on john object.

{
  id: id,
  ...
}

Let's introduce an association into the mix:

class CarJson < JsonDumper::Base
  def preview
    {
      id: id,
      name: name,
    }
  end
end

class HumanJson < JsonDumper::Base
  # ...
  def details
    preview.merge(
      car: CarJson.preview(car)
    )
  end
end

ferrari = Car.create(
  name: 'Ferrari',
)
john.car = ferrari

json = HumanJson.details(john)
json == {
  id: 1,
  first_name: 'John',
  last_name: 'Doe',
  born_at: '09/19/1997',
  car: {
    id: 1,
    name: 'Ferrari'
  }
}

This structure provides a very clean way to specify dependencies for ActiveRecord preloader:

class HumanJson < JsonDumper::Base
  def preview
    # ...
  end

  def preview_preload
    {}
  end

  def details
    # ...
  end

  def details_preload
    preview_preload.merge(car: [])
  end
end

Furthermore you can omit defining preview_preload because JsonDumper returns empty hashes ({}) whenever a method does not exist and its name ends with _preload.

You can utilize it in the following way:

preloader = ActiveRecord::Base::Preloader.new
preloader.preload(john, HumanJson.details_preload)
json = HumanJson.details(john)

Another cool feature that you can now do is to do both preloading and serialization in a single command via fetch_METHOD_NAME. This creates a special JsonDumper::Delayed object which delays its execution until it's time to render. This allows to do preloading at render time.

Since this is a common operation you can include JsonDumper::Base in your controller.

class HumansController < ActionController::Base
  include JsonDumper::Helper

  def show
    human = Human.find(params[:id])
    json = dumper_json(
      my_human: HumanJson.fetch_details(human)
    )
    render json: json
  end

  # OR

  def show
    human = Human.find(params[:id])
    render_dumper_json(
      my_human: HumanJson.fetch_details(human)
    )
  end
end

# going to render:
{
  myHuman: {
    id: 1,
    firstName: 'John',
    lastName: 'Doe',
    bornAt: '09/19/1997',
    car: {
      id: 1,
      name: 'Ferrari'
    }
  }
}

Take a note that dumper_json also camelizes your keys.

Usage with Gon

This gem also provides a seamless integration with Gon gem. The above example could be rewritten in the following way:

class HumansController < ActionController::Base
  def show
    human = Human.find(params[:id])
    gon.my_human = HumanJson.fetch_details(human)
  end
end

Later in your javascript:

    console.log(gon.myHuman);

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/therusskiy/json_dumper. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Check it out here