Ruby on RailsのJSON Serializer検討(2024)
概要
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年現在開発が活発ではない印象。
実装例
class UserSerializer < ActiveModel::Serializer
attributes :id, :name
end
# 呼び出し
UserSerializer.new(@user).as_json
jbuilder
Rails標準で入っているテンプレートベースのシリアライザー
凝った使い方をするとパフォーマンスの懸念があるらしい
実装例
# app/views/users/show.json.jbuilder
json.id @user.id
json.name @user.name
Active Model JSON Serializer
こちらもRails標準のシリアライザー
名前が active_model_serializers
と被っているので紛らわしいが、こちらはGemではなく標準で使える。
実装例
# Modelをjsonで表現する
@user.as_json
# 項目の選択も可能
@user.as_json(only: [:id, :name])
@user.as_json(except: [:created_at])
jb
jbuilderと似たテンプレートベースのシリアライザー
jbuilderと比較して高速らしい。
実装例
# app/views/users/show.json.jb
json = {
id: @user.id,
name: @user.name
}
json
jsonapi-serializer
元々はNetflixが開発したfast_jsonapiをフォークしたものらしい。(こちらは現在メンテされていない)
v2がメンテナンスモードになっており、v3の方もちょっと調べたが活発に開発されていない可能性がありそう
実装例
clsss UserSerializer
include JSONAPI::Serializer
end
json = UserSerializer.new(@user).serializable_hash.to_json
blueprinter
シンプル且つ、パフォーマンスも出るような設計になっているらしい。
使い勝手もActiveModelSerializersに近い。
実装例
class UserBlueprint < Blueprinter::Base
identifier :id
fields :name
end
UserBlueprint.render(@user)
alba
blueprinter同様、使い勝手もActiveModelSerializersに近い。
Blueprinter shares some concepts with Alba
公式のREADMEに書いてあるが、blueprinterと同じような概念があるらしい
実装例
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