2020年11月10日火曜日

Ruby でオブジェクトを簡単に JSON シリアライズする方法

概要

Rails を使っている場合には ActiveModelSerializers があります
単体で使用している場合には使いづらいケースもあります
そんな場合にはシンプルに使える Blueprinter が使えます

環境

  • macOS 10.15.7
  • Ruby 2.7.1p83
    • blueprinter 0.25.1

準備

  • bundle init
  • vim Gemfile
gem "blueprinter"
  • bundle install

まずは普通のクラスを定義

テスト用に作成します
これを JSON にシリアライズしてみます

class User
  def initialize(name, age)
    @name = name
    @age = age
  end

  def show_profile
    puts @name
    puts @age
  end

  attr_accessor :name, :age
end

u = User.new("hawksnowlog", 10)
u.show_profile

シリアライズできるようにする

blueprinter と json を require します
json を require しないと uninitialized constant Blueprinter::Configuration::JSON (NameError) になります
シリアライズするクラスは Blueprinter::Base を継承します

あとは JSON のフィールドとして表示するインスタンス変数を fileds で定義します
JSON として出力する場合は render メソッドをコールして生成した User クラスのオブジェクトを渡します

require 'blueprinter'
require 'json'

class User < Blueprinter::Base
  fields :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end

  def show_profile
    puts @name
    puts @age
  end

  attr_accessor :name, :age
end

u = User.new("hawksnowlog", 10)
puts User.render(u)

識別子の自動付与

identifier を使います
uuid というメソッドを定義するか identifier の引数にブロックを与えることで uuid として設定する値を決めることができます
今回は SecureRandom.uuid の値を返していますが本来はデータベースなどから識別子を取得して返却するようになると思います

require 'blueprinter'
require 'json'
require 'securerandom'

class User < Blueprinter::Base
  identifier :uuid
  fields :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end

  def uuid
    SecureRandom.uuid
  end

  def show_profile
    puts @name
    puts @age
  end

  attr_accessor :name, :age
end

u = User.new("hawksnowlog", 10)
puts User.render(u)

フィールドのデフォルト値の設定

nil などでインスタンス変数の値が初期化されていない場合に返却するデフォルトの値を設定することができます
Blueprinter 全体の設定をするには Blueprint.configure を使います
ここで config.field_default にデフォルトの値を設定することができます

require 'blueprinter'
require 'json'
require 'securerandom'

class User < Blueprinter::Base
  identifier :uuid
  fields :name, :age

  Blueprinter.configure do |config|
    config.field_default = "N/A"
    config.association_default = {}
  end

  def initialize(name, age)
    @name = name
    @age = age
  end

  def uuid
    SecureRandom.uuid
  end

  def show_profile
    puts @name
    puts @age
  end

  attr_accessor :name, :age
end

u = User.new("hawksnowlog", nil)
puts User.render(u)

最後に

簡単ですが Blueprinter の使い方を紹介しました
to_json などを実装して自分でシリアライズするメソッドを実装しても問題ないですがデフォルト値やバリデーションなどを考えるとすでにその辺りが実装されている Blueprinter が便利かなと思います

既存のクラスを拡張する必要があるのでそこがネックになる可能性もありますが新規のクラスであれば簡単に拡張できると思います

参考サイト

0 件のコメント:

コメントを投稿