RubyのYAML出力でkeyがシンボルになってしまうのを回避
CSV(TSV)をインポートしてYAMLに変換しようとした。
require 'csv' require 'yaml' tsv = CSV.table("import.tsv", { :col_sep => "\t" }) tsv.each do |line| id = line[:id] open("result/#{id}.yml", "w") do |f| f.write(YAML.dump(line.to_hash)) end end
すると、下記のように先頭にコロンがついてしまう。
これはRuby向けのYAML方言っぽいし、手で書くときにはそうしたくない。
--- :id: 1 :name: xxxx :age: xx
出力のstyleを変更するオプションがないかなとググってみても、見つけたものはうまく動かなかった。
散々悩んだ挙句、あることに気づいた。既存のYAMLファイルを読み込んでそれに対して更新を行った場合はこの結果にならない。だからテンプレートとなるYAMLファイルを用意し、それに対してインポートするデータをはめ込んでいく方式だ。
--- id: '' name: '' age: ''
require 'csv' require 'yaml' tsv = CSV.table("import.tsv", { :col_sep => "\t" }) tsv.each do |line| tmpl = YAML.load_file("template.yml") tmpl.map do |key, val| tmpl[key] = line[key.to_sym] end id = line[:id] open("result/#{id}.yml", "w") do |f| f.write(YAML.dump(tmpl)) end end
--- id: 1 name: xxxx age: xx
できた!!
ちなみに、何が違うのかデバッグしてみたところ、テンプレートから取得してきた場合は各データの型がHashではなくArray
だった。
あと、ループ内でテンプレートを読み込み直しているから遅いんだけど、まあ大した件数じゃないからいいや。clone
とかdup
とか使うのかな?わからん。外側に出しても必ず各フィールドが上書きされるから大丈夫だと思うけどね。