添付ライブラリ: yaml & json & csv

yamlはハッシュと配列を表現するためのフォーマットで、rubyスクリプト上でも文字列として扱うことが出来る。

8] pry(main)> yaml_data = <<-DATA
[8] pry(main)* - red
[8] pry(main)* - green
[8] pry(main)* - yello
[8] pry(main)* DATA   
=> "- red\n- green\n- yello\n"
[9] pry(main)> YAML.load(yaml_data)
=> ["red", "green", "yello"]

複数のyamlが記録されていても、最初のyamlしか読み込まれない。なおそのためのセパレータはハイフン3つぶんで、これを超えると文法エラーとなる。

[12] pry(main)> yaml_data = <<-DATA
[12] pry(main)* - yello
[12] pry(main)* - pink
[12] pry(main)* - brown
[12] pry(main)* ---
[12] pry(main)* - orange
[12] pry(main)* - red
[12] pry(main)* - green
[12] pry(main)* DATA   
=> "- yello\n- pink\n- brown\n---\n- orange\n- red\n- green\n"
[13] pry(main)> YAML.load(yaml_data)
=> ["yello", "pink", "brown"]

また、yamlファイルからロードする場合は、load_fileを用いる。

また、複数の読み込みを行いたい場合はload_streamを用いる。

[14] pry(main)> yaml_data = <<-DATA
[14] pry(main)* - green
[14] pry(main)* - red
[14] pry(main)* - pink
[14] pry(main)* ---
[14] pry(main)* - orange
[14] pry(main)* - white
[14] pry(main)* - brown
[14] pry(main)* DATA   
=> "- green\n- red\n- pink\n---\n- orange\n- white\n- brown\n"
[15] pry(main)> YAML.load_stream(yaml_data)
=> [["green", "red", "pink"], ["orange", "white", "brown"]]

load_documentsは複数のyamlをロードして、一つ一つに対してブロック内で処理を行うことが出来る「each的」メソッド。

yamlの書き込み、ファイルへの保存はdumpというメソッドを用いる。引数を指定したなれば、文字列として返される。

irb(main):001:0> yaml_d = <<-DATA
irb(main):002:0" - red
irb(main):003:0" - green
irb(main):004:0" - orange
irb(main):005:0" ---
irb(main):006:0" - north
irb(main):007:0" - west
irb(main):008:0" - east
irb(main):009:0" DATA
=> "- red\n- green\n- orange\n---\n- north\n- west\n- east\n"
irb(main):011:0> require "yaml"
=> true
irb(main):013:0> y = YAML.load_stream(yaml_d)
=> [["red", "green", "orange"], ["north", "west", "east"]]
irb(main):016:0> YAML.dump(y)
=> "---\n- - red\n  - green\n  - orange\n- - north\n  - west\n  - east\n"
irb(main):017:0> YAML.dump_stream(y)
=> "---\n- - red\n  - green\n  - orange\n- - north\n  - west\n  - east\n"

dumpもdump_streamも文字列化すると、配列の入れ子は一つの配列のように扱われているように見えるが、ちゃんと2つの独立した配列として扱われているのがputsを使うとわかる。

irb(main):018:0> y2 = YAML.dump_stream(y)
=> "---\n- - red\n  - green\n  - orange\n- - north\n  - west\n  - east\n"
irb(main):021:0> puts y2
---
- - red
  - green
  - orange
- - north
  - west
  - east
=> nil

json

yamlと同様にjsonにもjson文字列からオブジェクトに変換するメソッドが用意されている。yamlと同様loadのほかにparseというメソッドが用意されている。また、loadを使用した場合、第二引数にProcオブジェクトを指定して、オブジェクトに変換された後のオブジェクトに対する処理を指定することが出来る。

*parseだと、第二引数の指定はエラー

irb(main):007:0> JSON.load(json,lambda{|x| p x})
"RED"
"BLUE"
"GREEN"
["RED", "BLUE", "GREEN"]
=> ["RED", "BLUE", "GREEN"]
irb(main):008:0> JSON.parse(json,lambda{|x| p x})
TypeError: no implicit conversion of Proc into Hash
        from /home/pyons/.rbenv/versions/2.1.0/lib/ruby/2.1.0/json/common.rb:155:in `initialize'
        from /home/pyons/.rbenv/versions/2.1.0/lib/ruby/2.1.0/json/common.rb:155:in `new'
        from /home/pyons/.rbenv/versions/2.1.0/lib/ruby/2.1.0/json/common.rb:155:in `parse'
        from (irb):8
        from /home/pyons/.rbenv/versions/2.1.0/bin/irb:11:in `<main>'

また、変換時にjson入れ子の深さの最大値を指定したり、無限大を許容したりと、様々なオプションが用意されている。

JSONの書き込みを行うメソッドも用意されている。オブジェクトの参照の入れ子の深さを指定するオプションとしてlimitが用意されており、それを超える参照が行われるとArgumentErrorが発生する。

csv

CSVの読み込みは「各行」で行われる。ブロックを渡すと各行を配列として取得することが出来る。 ブロックに渡さないと、CSVファイルとして処理される。

require "csv"
csv = CSV.open("sheet1.csv")
p csv.class # CSV
p csv # <#CSV io_type:File io_path:"sheet1.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\r\n" quote_char:"\"">

csv.each do |row|
  p row 
end
# [nil, "明日", "明後日", "明々後日"]
# ["東京", "晴れ", "雪", "晴れ"]
# ["群馬", "雨", "豪雨", "晴れ"]
# ["埼玉", "曇り", "曇り", "雨"]
# ["栃木", "晴れ", "雨", "曇り"]

書き込みを行う場合は、ブロックに対して、配列を渡すような形で追記していく。