読者です 読者をやめる 読者になる 読者になる

Ruby 1.9 以降で JSON を扱う

RubyJSON を扱いたいと思って調べてみると、 Ruby 1.9 で標準添付ライブラリに加わったということを知ったのですが、いまいち情報がみつからなかったのでまとめてみました。

(追記) 1.9 の json ライブラリは gem の json パッケージのものと同じものみたいです(バージョンの差はあるかもしれませんが)。ちゃんと調べてませんが 1.9 の段階で既存のパッケージが取り込まれたかたちなのだと思います。ですので、以下は Ruby 1.8 系統に rubygemsjson をいれたときでも同様の操作で JSON を扱えるはずです。

JSON からオブジェクトに

JSON 形式の文字列から配列/ハッシュへ

JSON から配列/ハッシュへは JSON.parse(str) もしくは JSON.load(str) で変換できます。

require 'json'

JSON.parse('[1, 2, 3]')
#=> [1, 2, 3]

JSON.parse('{"foo" : "bar"}')
#=> {"foo"=>"bar"}

ファイルから配列/ハッシュへ

JSON.load(io) は文字列だけでなく IO から読み込んだものを変換することができます。

require 'json'

# file.json には [1, 2, 3, {"foo" : "bar"}] と書かれているとき
open("file.json") do |io|
	JSON.load(io)
	#=> [1, 2, 3, {"foo"=>"bar"}]
end

変換した各オブジェクトを手続きとして処理する

JSON.load(str_or_io, proc) の第二引数に手続きオブジェクトが与えられると、変換したオブジェクトを引数に手続きを呼び出すことができます。

require 'json'

JSON.load('[1, 2, 3, {"foo" : "bar"}]', proc{|v| p v})
#=> [1, 2, 3, {"foo"=>"bar"}]

# 以下が表示される
# 1
# 2
# 3
# "foo"
# "bar"
# {"foo"=>"bar"}
# [1, 2, 3, {"foo"=>"bar"}]

オブジェクトから JSON

配列/ハッシュから JSON 形式の文字列へ

逆に配列ないしはハッシュから JSON へ変換するには JSON.generate(obj) を使います。

require 'json'

JSON.generate({"foo" => "bar"})
#=> "{\"foo\":\"bar\"}"

その他のオブジェクトから JSON で使える文字列へ

多くのクラスにも #to_json が定義されています。

require 'json'

1.to_json #=> "1"
Time.local(2011, 12, 5, 7, 29, 33).to_json
#=> "\"2011-12-05 07:29:33 +0900\""

きれいに整形する

JSON.pretty_generate(obj)複数の行を使って、更に読みやすい形式で生成します。

require 'json'

data = [1, 2, 3, {"foo" => "bar"}]
JSON.generate(data)
#=> "[1,2,3,{\"foo\":\"bar\"}]"

JSON.pretty_generate(data)
#=> "[\n  1,\n  2,\n  3,\n  {\n    \"foo\": \"bar\"\n  }\n]"

配列/ハッシュからファイルへ

JSON.dump(obj, io) を使うと書き込みモードの IO に、生成した JSON を書き込むことができます。

require 'json'

open("file.json", "w") do |io|
	JSON.dump([1, 2, 3, {"foo" => "bar"}], io)
	# file.json に [1,2,3,{"foo":"bar"}] と書き込まれる
end

そのほか

もっと簡潔に変換する

JSON[str_or_obj] を使うと、引数が文字列のときは JSON.parse 、配列/ハッシュのときは JSON.generate として処理されます。

require 'json'

JSON['[1, 2, 3, {"foo":"bar"}]']
#=> [1, 2, 3, {"foo"=>"bar"}]

JSON[[1, 2, 3, {"foo"=>"bar"}]]
#=> "[1,2,3,{\"foo\":\"bar\"}]"

オプションとその他の情報について

JSON.parse(str, opts) など第二引数などでオプションをとるものもあります。

require 'json'

JSON.parse('{"foo":"bar"}')
#=> {"foo"=>"bar"}

JSON.parse('{"foo":"bar"}', {:symbolize_names => true})
#=> {:foo=>"bar"}

詳細についてここでは省きます。詳しくは以下のページやソース内のコメントを確認してください(ソース内でしか載っていないものもあります)。