おはよーございます。
以前書いた記事で課題にしていた、RubyオブジェクトをJSONに変換する方法。
つい先日解決しました!
結論から書くとこんな感じです。
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とか書いたほうがもっとわかりやすくなったかも。。
次回から英語風に読める特長も活かしつつ、プログラムを書いていきます。
では、また!