💎

Ruby on RailsのJSON Serializer検討(2024)

2024/09/18に公開

概要

Ruby on RailsでREST APIを実装する際にJSONに整形してレスポンスを返す必要があります。

いくつか手法が存在するため、調べた内容をまとめます。

選択肢

以下に今回検討した選択肢と実装例をまとめます。

直接renderする

一番シンプルな方法。
Gemを入れる必要もなく、シンプルに実装することができる。

実装例

# 1項目程度
render json: { user: @user }

# 固定文字
render json: { error: 'エラーだよ' }, status: :internal_server_error

# 配列
render json: { users: @users }

active_model_serializers

rails serializer で検索すると多くの記事が出てくる。
しかし、2024年現在開発が活発ではない印象。

https://github.com/rails-api/active_model_serializers

実装例

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name
end

# 呼び出し
UserSerializer.new(@user).as_json

jbuilder

Rails標準で入っているテンプレートベースのシリアライザー
凝った使い方をするとパフォーマンスの懸念があるらしい
https://github.com/rails/jbuilder

実装例

# app/views/users/show.json.jbuilder
json.id @user.id
json.name @user.name

Active Model JSON Serializer

こちらもRails標準のシリアライザー
名前が active_model_serializers と被っているので紛らわしいが、こちらはGemではなく標準で使える。

https://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html

実装例

# Modelをjsonで表現する
@user.as_json
# 項目の選択も可能
@user.as_json(only: [:id, :name])
@user.as_json(except: [:created_at])

jb

jbuilderと似たテンプレートベースのシリアライザー
jbuilderと比較して高速らしい。
https://github.com/amatsuda/jb

実装例

# app/views/users/show.json.jb
json = {
  id: @user.id,
  name: @user.name
}

json

jsonapi-serializer

元々はNetflixが開発したfast_jsonapiをフォークしたものらしい。(こちらは現在メンテされていない)

v2がメンテナンスモードになっており、v3の方もちょっと調べたが活発に開発されていない可能性がありそう
https://github.com/jsonapi-serializer/jsonapi-serializer

実装例

clsss UserSerializer
  include JSONAPI::Serializer
end

json = UserSerializer.new(@user).serializable_hash.to_json

blueprinter

シンプル且つ、パフォーマンスも出るような設計になっているらしい。
使い勝手もActiveModelSerializersに近い。
https://github.com/procore-oss/blueprinter

実装例

class UserBlueprint < Blueprinter::Base
  identifier :id

  fields :name
end

UserBlueprint.render(@user)

alba

blueprinter同様、使い勝手もActiveModelSerializersに近い。

Blueprinter shares some concepts with Alba

公式のREADMEに書いてあるが、blueprinterと同じような概念があるらしい

https://github.com/okuramasafumi/alba

実装例

class UserResource
  include Alba::Resource

  root_key :user

  attributes :id, :name
end

UserResource.new(@user).serialize

選定のポイント

比較してみて、実装方法も特徴も異なるので選定に必要なポイントをまとめます(個人的観点です)

  • 定期的にメンテナンスが行われていること
    • 自分でメンテしよう!という気合いがあれば話は別だが、重要なポイント
  • 検索した時にある程度文献があるか?
    • 日本語はもちろん、英語でも文献がある?
    • (無いなら書こう!の精神も必要ではあるがそれは置いておく)
  • テンプレートベース(DSL)かRubyベースか
    • ここはどちらが良いのか?を考える必要がある
    • MVCベースで考えるとviewにテンプレートを置き換えるだけなので馴染みはありそう
    • テンプレートにビジネスロジックが入り込む可能性があるため、そこがちゃんと縛れるか
    • RubyベースだとControllerから直接呼び出すことになるため、関連性は掴みやすいしテストも分けて書ける
  • テストは容易にできるか?
    • テンプレートベースだとレスポンス全てをチェックする必要があるかも
    • 一部分のattributeだけテストしたい、そこに分岐があるとかならクラス定義の方が良さそう
  • パフォーマンス面はどうか?
    • もちろん速いに越したことはない
    • ただし、パフォーマンスがそこそこでも許容できる範囲であるか?
    • 大量にデータを扱う用件かどうかがポイントになりそう
  • キャッチアップのしやすさ
    • 開発メンバーの熟練度で考える
    • 自由度を上げ過ぎるとなんでもできてしまってパフォーマンスやセキュリティの懸念も発生する
    • ここも状況に合わせて柔軟に選ぶ必要がある

まとめ

ざっとこんな感じでまとめてみました。
他にもこのSerializerいいよ!みたいなものがありましたら是非ご連絡ください。

Discussion