OcO’s KAKI-PPANASHI

オシオトシマサの書きっぱなしジャーマン

【趣味ではじめるRuby】自分で作ったクラスをJSONに変換する方法

おはよーございます。

以前書いた記事で課題にしていた、RubyオブジェクトをJSONに変換する方法。

つい先日解決しました!

osio-toshimasa.hatenablog.com

結論から書くとこんな感じです。

class TestData
  attr_accessor :num, :str, :data_hash, :data_array

  def initialize (num, str, data_hash, data_array)
    @num = num
    @str = str
    @data_hash = data_hash
    @data_array = data_array
  end

  # 定義されているインスタンス変数をハッシュオブジェトに変換する。
  # Keyはインスタンス変数名から@を省いた名前
  # Valueはインスタンス変数そのままのデータ
  def to_hash
    hash = {}
    self.instance_variables.each do |v|
      hash.store(v.to_s.gsub('@', ''), self.instance_variable_get(v))
    end
    hash
  end

  # JSONデータにする
  def to_json
    JSON.generate(self.to_hash)
  end

end

to_hashというメソッドとto_jsonというメソッドを追加しました。

なかでもto_hashがキモでself.instance_variablesで自身のインスタンス変数名を全て取得して、新しく作成したhash変数のKey名に使いました。

instance_variablesはインスタンス変数なので先頭に@がつきます。

最終的にJSONのキー名として使いたいので@はgsubメソッドで削除しています。よくよく思えば先頭一文字削除するメソッドでもよかったかも。

hash変数のvalueはself.instance_variable_getメソッドでインスタンス変数名から値を取りだしそのまま放り込んでいます。

実際のJSON生成はto_jsonメソッドで、さきほど作ったto_hashで得られたハッシュオブジェクトをJSON.generateに渡してJSONデータ化しています。

簡単なデータ構造だけなのであれば、以前書いた記事で紹介した

def self.test_data()
  JSON.generate(
    num: 1,
    str: '2',
    data_hash: {test: 1, test2: "test_str"},
    data_array: [1, "2", 3] )
end

こんな感じで直接ハッシュオブジェクトを作ってもいいのですが、与えたデータの計算が必要だったり、文字列を加工してからデータを返すときは、クラスオブジェクトにまとめて最後にto_jsonするほうが、プログラムがすっきりしそうです。

余談なんですが、以下のコードも気になっていまして

  def to_hash
    # ここと
    hash = {}

 中略
    
    # ここがなんか無駄に見える
    hash
  end

このように書き換えました。結果同じなんですけど、すっきり晴れやかな気分になっただけの自己満コードです。

  def to_hash
   # reduceを使うとハッシュの初期化と更新がスッキリ
    self.instance_variables.reduce({}) do |hash, v|
      # deleteのがわかりやすいような気がして変えました。
      hash.store(v.to_s.delete('@'), self.instance_variable_get(v))
      hash
    end
  end

ほんのすこしですが、コードが短くなってスマートに見えます。

細かいところですけど、少し工夫するだけで便利になったりコードがスッキリするのが個人的楽しいポイントです😀

あと、こうしてブログに書いてみて気づいたのですが、Rubyのコードって英語を喋っているみたいにプログラムが書けるんですよね。まるでコードがしゃべっているみたい感じます。

英語っぽく読めば何やっているか直感的に想像できるっていうのは、プログラミング不慣れな方でもとっつきやすい特長ではないでしょうか?

それでいくと、上のコードにでてくる変数のvとかわかりづらいですね😅 vとか省略せずvariableとか書いたほうがもっとわかりやすくなったかも。。

次回から英語風に読める特長も活かしつつ、プログラムを書いていきます。

では、また!