akishin999の日記

調べた事などを書いて行きます。

出力される JSON の形式をカスタマイズする

to_json で出力される JSON 文字列の形式をカスタマイズする方法を調べてみました。
Ruby 2.0.0p247 で確認しています。

まずは普通に to_json してみるとこんな感じ。

require 'json'

t = Time.local(1978, 5, 31, 19, 30, 40, 205000)
h = {id: 100, name: "example", created_at: t}

puts h.to_json
#=> {"id":100,"name":"example","created_at":"1978-05-31 19:30:40 +0900"}

# JSON.generate でも同じ
puts JSON.generate(h)
#=> {"id":100,"name":"example","created_at":"1978-05-31 19:30:40 +0900"}

この JSON 文字列をカスタマイズするためには、該当クラスの to_json メソッドをオーバーライドすれば良いようです。
ここでは Time 型のフォーマットを変更してみます。

require 'json'

t = Time.local(1978, 5, 31, 19, 30, 40, 205000)
h = {id: 100, name: "example", created_at: t}

# to_json をオーバーライド
class Time
  def to_json(*a)
    strftime('%Y-%m-%d %H:%M:%S.%L').to_json(*a)
  end
end

puts h.to_json
#=> {"id":100,"name":"example","created_at":"1978-05-31 19:30:40.205"}

# JSON.generate でも同じ
puts JSON.generate(h)
#=> {"id":100,"name":"example","created_at":"1978-05-31 19:30:40.205"}

指定したフォーマットで出力されています。
これで日付フォーマットが規定されているような場合でも to_json で一発変換できますね。

ちなみに深くは追っていないのですが、Rails 内で ActiveRecord のモデルオブジェクトに対して to_json した場合、何故か上記のようにオーバーライドしても反映されていませんでした。
その場合、to_json ではなく、JSON.generate を使ってみたところ、ちゃんと指定した形式で JSON 文字列が出力されました。

この辺りはそのうちちゃんと調べよう。