Gem Version Build Status Coverage Status Maintainability GitHub code size in bytes GitHub

Alba

Alba is the fastest JSON serializer for Ruby.

Why yet another JSON serializer?

We know that there are several other JSON serializers for Ruby around, but none of them made us satisfied.

Alba has some advantages over other JSON serializers which we've wanted to have.

Easy to understand

DSL is great. It makes the coding experience natural and intuitive. However, remembering lots of DSL requires us a lot of effort. Unfortunately, most of the existing libraries have implemented their features via DSL and it's not easy to understand how they behave entirely. Alba's core DSL are only four (attributes, attribute, one and many) so it's easy to understand how to use.

Alba is also understandable internally. The codebase is much smaller than the alternatives. In fact, it's less than 300 lines of code. Look at the code on GitHub and you'll be surprised how simple it is!

Performance

Alba is faster than most of the alternatives. We have a benchmark.

Installation

Add this line to your application's Gemfile:

gem 'alba'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install alba

Supported Ruby versions

Alba supports CRuby 2.5.7 and higher and latest TruffleRuby.

Documentation

You can find the documentation on RubyDoc.

Features

  • Resource-based serialization
  • Arbitrary attribute definition
  • One and many association with the ability to define them inline
  • Adding condition and filter to association
  • Parameters can be injected and used in attributes and associations
  • Setting root key separately in Serializer
  • Adding metadata
  • Selectable backend
  • No runtime dependencies

Anti features

  • Sorting keys
  • Class level support of parameters
  • Supporting all existing JSON encoder/decoder
  • Cache
  • JSON:API support
  • Association name inflection
  • And many others

Usage

Configuration

Alba's configuration is fairly simple.

Backend

Backend is the actual part serializing an object into JSON. Alba supports these backends.

  • Oj, the fastest. Gem installation required.
  • active_support, mostly for Rails. Gem installation required.
  • default or json, with no external dependencies.

You can set a backend like this:

Alba.backend = :oj

Simple serialization with key

class User
  attr_accessor :id, :name, :email, :created_at, :updated_at
  def initialize(id, name, email)
    @id = id
    @name = name
    @email = email
    @created_at = Time.now
    @updated_at = Time.now
  end
end

class UserResource
  include Alba::Resource

  attributes :id, :name

  attribute :name_with_email do |resource|
    "#{resource.name}: #{resource.email}"
  end
end

class SerializerWithKey
  include Alba::Serializer

  set key: :user
end

user = User.new(1, 'Masafumi OKURA', '[email protected]')
UserResource.new(user).serialize
# => "{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: [email protected]\"}"

Serialization with associations

class User
  attr_reader :id, :created_at, :updated_at
  attr_accessor :articles

  def initialize(id)
    @id = id
    @created_at = Time.now
    @updated_at = Time.now
    @articles = []
  end
end

class Article
  attr_accessor :user_id, :title, :body

  def initialize(user_id, title, body)
    @user_id = user_id
    @title = title
    @body = body
  end
end

class ArticleResource
  include Alba::Resource

  attributes :title
end

class UserResource
  include Alba::Resource

  attributes :id

  many :articles, resource: ArticleResource
end

user = User.new(1)
article1 = Article.new(1, 'Hello World!', 'Hello World!!!')
user.articles << article1
article2 = Article.new(2, 'Super nice', 'Really nice!')
user.articles << article2

UserResource.new(user).serialize
# => '{"id":1,"articles":[{"title":"Hello World!"},{"title":"Super nice"}]}'

Inline definition with Alba.serialize

Alba.serialize method is a shortcut to define everything inline.

Alba.serialize(user, with: proc { set key: :foo }) do
  attributes :id
  many :articles do
    attributes :title, :body
  end
end
# => '{"foo":{"id":1,"articles":[{"title":"Hello World!","body":"Hello World!!!"},{"title":"Super nice","body":"Really nice!"}]}}'

Although this might be useful sometimes, it's generally recommended to define a class for both Resource and Serializer.

Inheritance and Ignorance

You can exclude or ignore certain attributes using ignoring.

class Foo
  attr_accessor :id, :name, :body

  def initialize(id, name, body)
    @id = id
    @name = name
    @body = body
  end
end

class GenericFooResource
  include Alba::Resource

  attributes :id, :name, :body
end

class RestrictedFooResouce < GenericFooResource
  ignoring :id, :body
end

RestrictedFooResouce.new(foo).serialize
# => '{"name":"my foo"}'
end

Comparison

Alba is faster than alternatives. For a performance benchmark, see https://gist.github.com/okuramasafumi/4e375525bd3a28e4ca812d2a3b3e5829.

Rails

When you use Alba in Rails, you can create an initializer file with the line below for compatibility with Rails JSON encoder.

Alba.backend = :active_support

Why named "Alba"?

The name "Alba" comes from "albatross", a kind of birds. In Japanese, this bird is called "Aho-dori", which means "stupid bird". I find it funny because in fact albatrosses fly really fast. I hope Alba looks stupid but in fact it does its job quick.

Alba internals

Alba has three component, Serializer, Resource and Value (Value is conceptual and not implemented directly).

Serializer is a component responsible for rendering JSON output with Resource. Serializer can add more data to Resource such as metadata. Users can define one single Serializer and reuse it for all Resources. The main interface is #serialize.

Resource is a component responsible for defining how an object (or a collection of objects) is converted into JSON. The difference between Serializer and Resource is that while Serializer can add arbitrary data into JSON, Resource can get data only from the object under it. The main interface is #serializable_hash.

One and Many are the special object fetching other resources and converting them into Hash.

The main Alba module holds config values and one convenience method, .serialize.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test 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/okuramasafumi/alba. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

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

Code of Conduct

Everyone interacting in the Alba project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.