No release in over a year
Generate JSON bypassing ActiveRecord object building. Directly from PG result
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 5.0, < 7.1
>= 1.1.1, < 2.0

Runtime

~> 3.13
 Project Readme

Fast::Json::Serializer

This gem generates the JSON bypassing ActiveRecord object creation, which make JSON generation blazing fast! It uses ActiveRecord::Base.connection.execute method which returns PG::Result. JSON is generated by iterating over the collection.

Installation

Add this line to your application's Gemfile:

gem 'fast-json-serializer'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install fast-json-serializer

Usage

Create a app/serializers/application_serializer.rb with the following code:

# app/serializers/application_serializer.rb

require 'fast/json/serializer/base'

class ApplicationSerializer < Fast::Json::Serializer::Base
end

Make the other serializers a subclass of the ApplicationSerializer class

# app/serializers/post_serializer.rb

class PostSerializer < ApplicationSerializer
  # enable FastJsonapi format by uncommenting this line
  # set_type :post

  attributes :id, :title, :creator_name, :creator_email

  # use a ruby/rails formatter
  attribute :created_at, format: :to_s
  attribute :updated_at, format: :to_s

  # rename the json key name
  attribute :created_at_epoch, column_name: :created_at, format: :to_i
  attribute :updated_at_epoch, column_name: :updated_at, format: :to_i

  # use custom method
  attribute :created_at_ist do |serializer, hash|
    serializer.ist_time(hash['created_at'])
  end

  attribute :updated_at_ist do |serializer, hash|
    serializer.ist_time(hash['updated_at'])
  end

  # a class method can be used as well 
  def ist_time(timestamp)
    return unless timestamp
    
    timestamp.in_time_zone("Kolkata").strftime('%A - %b %d, %Y')
  end
end

Formatting of the JSON

Currently, it supports two formats, key-value, and FastJsonapi format

PostSerializer.new(Post.limit(10)).serialized_json

produces, with set_type :post enabled:

{
  "data": [
    {
      "id": 1,
      "type": "post",
      "attributes": {
        "id": 1,
        "title": "Tacos",
        "creator_name": "Ella Erdman",
        "creator_email": "sean.zieme@smitham.name",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 2,
      "type": "post",
      "attributes": {
        "id": 2,
        "title": "Barbecue Ribs",
        "creator_name": "Mrs. Fern Yundt",
        "creator_email": "rafael.simonis@metz.com",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 69,
      "type": "post",
      "attributes": {
        "id": 69,
        "title": "French Fries with Sausages",
        "creator_name": "Vance Connelly",
        "creator_email": "leslee_langosh@mann.biz",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 3,
      "type": "post",
      "attributes": {
        "id": 3,
        "title": "Pork Belly Buns",
        "creator_name": "Mrs. Willie Green",
        "creator_email": "aracely_tromp@torphy-jenkins.info",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 4,
      "type": "post",
      "attributes": {
        "id": 4,
        "title": "Peking Duck",
        "creator_name": "Joselyn VonRueden",
        "creator_email": "marianna_damore@lehner-metz.org",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 5,
      "type": "post",
      "attributes": {
        "id": 5,
        "title": "Hummus",
        "creator_name": "Stacee Pfannerstill",
        "creator_email": "barrett_johnston@weimann-gottlieb.name",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 6,
      "type": "post",
      "attributes": {
        "id": 6,
        "title": "California Maki",
        "creator_name": "Fidel Schroeder",
        "creator_email": "marquitta@kuvalis.info",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 7,
      "type": "post",
      "attributes": {
        "id": 7,
        "title": "French Toast",
        "creator_name": "Alvaro Berge",
        "creator_email": "randal_littel@fadel-fritsch.io",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 8,
      "type": "post",
      "attributes": {
        "id": 8,
        "title": "Arepas",
        "creator_name": "Alva Kris DO",
        "creator_email": "nathaniel_strosin@wintheiser.net",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    },
    {
      "id": 9,
      "type": "post",
      "attributes": {
        "id": 9,
        "title": "Meatballs with Sauce",
        "creator_name": "Willie Kuhic",
        "creator_email": "paul.rowe@mraz.biz",
        "created_at": "2022-10-13 05:51:08 UTC",
        "updated_at": "2022-10-13 05:51:08 UTC",
        "created_at_epoch": 1665640268,
        "updated_at_epoch": 1665640268,
        "created_at_ist": "Thursday - Oct 13, 2022",
        "updated_at_ist": "Thursday - Oct 13, 2022"
      }
    }
  ]
}

and with set_type :post disabled

[
  {
    "id": 1,
    "title": "Tacos",
    "creator_name": "Ella Erdman",
    "creator_email": "sean.zieme@smitham.name",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 2,
    "title": "Barbecue Ribs",
    "creator_name": "Mrs. Fern Yundt",
    "creator_email": "rafael.simonis@metz.com",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 69,
    "title": "French Fries with Sausages",
    "creator_name": "Vance Connelly",
    "creator_email": "leslee_langosh@mann.biz",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 3,
    "title": "Pork Belly Buns",
    "creator_name": "Mrs. Willie Green",
    "creator_email": "aracely_tromp@torphy-jenkins.info",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 4,
    "title": "Peking Duck",
    "creator_name": "Joselyn VonRueden",
    "creator_email": "marianna_damore@lehner-metz.org",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 5,
    "title": "Hummus",
    "creator_name": "Stacee Pfannerstill",
    "creator_email": "barrett_johnston@weimann-gottlieb.name",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 6,
    "title": "California Maki",
    "creator_name": "Fidel Schroeder",
    "creator_email": "marquitta@kuvalis.info",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 7,
    "title": "French Toast",
    "creator_name": "Alvaro Berge",
    "creator_email": "randal_littel@fadel-fritsch.io",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 8,
    "title": "Arepas",
    "creator_name": "Alva Kris DO",
    "creator_email": "nathaniel_strosin@wintheiser.net",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  },
  {
    "id": 9,
    "title": "Meatballs with Sauce",
    "creator_name": "Willie Kuhic",
    "creator_email": "paul.rowe@mraz.biz",
    "created_at": "2022-10-13 05:51:08 UTC",
    "updated_at": "2022-10-13 05:51:08 UTC",
    "created_at_epoch": 1665640268,
    "updated_at_epoch": 1665640268,
    "created_at_ist": "Thursday - Oct 13, 2022",
    "updated_at_ist": "Thursday - Oct 13, 2022"
  }
]

Benchmark, rails 7.0.2.3, ruby 3.0.3

  # there are 1100 posts in the DB, having fields 
  # :id, :title, :content, :creator_name, :creator_email, :created_at, :updated_at
  posts = Post.all
  s = PostSerializer.new(posts)

  n = 1000
  Benchmark.bm do |x|
    x.report("ActiveModel Serializer") { n.times { posts.to_json } }
    x.report("JSON:API Serialization") { n.times { PostJsonapiSerializer.new(posts).serializable_hash.to_json }}
    x.report("Blueprinter")            { n.times { PostBlueprint.render(posts) }}
    x.report("FastJsonSerializer")     { n.times { s.serialized_json } }
  end

  # result
  user                    system      total         real
  ActiveModel Serializer  35.373407   0.000000      35.373407 ( 35.380744)
  JSON:API Serialization  50.476935   0.043584      50.520519 ( 50.546082)
  Blueprinter             20.458713   0.000000      20.458713 ( 20.484488)
  FastJsonSerializer       5.239119   0.015989       5.255108 (  5.256627)

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/skarmakar/fast-json-serializer.