※ 「あなたがRails触る人なら見ておきたい「体系的な」豆知識」からの派生記事です。
yamlっていったい何者
-
yaml ain't markup language
の略 - 一般的な拡張子は
.yml
- 構造化データの表現方法
- あくまでも仕様を表すため仕様を処理する実装が別途必要
- 以下の言語でyamlを使用した実装がサポートされている
- Java
- JavaScript
- Perl
- PHP
- Python
- Tcl
- Ruby
- XML
※なお以下の説明ではrubyを使用します。
yamlの用途を端的に
- 各種設定ファイル
- データの保存・シリアライゼーション用
- データ交換用フォーマット
- ログファイル
yamlの特徴を端的に
- 読みやすく・書きやすく・わかりやすいという特徴がある
- インデントを使ってデータの階層構造を表す
- 終了タグが存在しない
- データ構造をハッシュ・配列・スカラーの三種類で表す
※例えばこんな感じで使う
input.yml
- d1
- d2
- d3
output.rb
require 'yaml'
d = YAML.load_file('input.yml')
p d
# => ["d1", "d2", "d3"]
- 上のやつは配列になる
- rubyファイル内では
require
をつかってyamlを導入する
yamlの書き方はよ
- 二種類の文法を主に使用する
- シーケンス(配列形式でデータ構造を表す)
- マッピング(ハッシュ形式でデータ構造を表す)
- コメントアウトはパウンド記号(
#
) - 入れ子構造はインデントで表すが留意事項が二点
- インデントにタブ記号は使えない
- 多くの場合インデントは空白2文字で表す
■シーケンス(配列形式)の書き方
- シーケンス =
-(空白)value
- 空白は必須であり無いとエラーが起こる
- 値の無い行の後に字下げを使うと入れ子構造になる
input.yml
- d1
- d2
- d3
#=> ["d1", "d2", "d3"]
- d1
-
- x1
- x2
- d3
#=> ["d1", ["x1", "x2"], "d3"]
■マッピング(ハッシュ形式)の書き方
- マッピング =
key:(空白)value
- こちらも空白は必須であり無いとエラーが起こる
- 値の無い行の後に字下げを使うと入れ子構造になる
input.yml
name : tomato
email: potato@gmail.com
#=> {"name"=>"tomato", "email"=>"potato@gmail.com"}
name : tomato
emails:
mainaddress: potato@gmail.com
subaddress : jagaimo@gmail.com
#=> {"name"=>"tomato", "emails"=>{"mainaddress"=>"potato@gmail.com", "subaddress"=>"jagaimo@gmail.com"}}
■複雑なデータ構造を表したい時
- シーケンスとマッピングはお互いに入れ子構造にできる
input.yml
# 配列の各値がハッシュ
- name : tomato
email: tomato@gmail.com
- name : potato
email: potato@gmail.com
#=> [{"name"=>"tomato", "email"=>"tomato@gmail.com"}, {"name"=>"potato", "email"=>"potato@gmail.com"}]
# ハッシュの各値が配列
names :
- tomato1
- tomato2
emails:
- potato1@gmail.com
- potato2@gmail.com
#=> {"names"=>["tomato1", "tomato2"], "emails"=>["potato1@gmail.com", "potato2@gmail.com"]}
■ブロックスタイルとフロースタイル
- シーケンスとマッピングには2種類の記法がある
- ブロックスタイル
- これまで見てきたyaml固有の書き方
- フロースタイル
- rubyに似通った書き方
input.yml
# ブロックスタイル
- tomato
- potato
#=> ["tomato", "potato"]
name : apple
color: red
#=> {"name"=>"apple", "color"=>"red"}
# フロースタイル
[tomato, potato]
#=> ["tomato", "potato"]
{name: apple, color: red}
#=> {"name"=>"apple", "color"=>"red"}
- 2種類の書き方を併用することで複雑なデータ構造を表現できる
yamlのデータ型を端的に
- データ型は自動で認識する
- 文字列っぽいものは文字列に、数値っぽいものは数値に
- 文字列に型変換する時にはダブルクォーテーション(
"
)で囲む
input.yml
str : tomato
int : 45
float : 5.21
bool1 : true
bool2 : false
blank : null
date : 2015-7-27
#=> {"str"=>"tomato", "int"=>45, "float"=>5.21, "bool1"=>true, "bool2"=>false, "blank"=>nil, "date"=>#<Date: 2015-07-27 ((2457231j,0s,0n),+0s,2299161j)>}
to_str1: "45"
to_str2: "true"
#=> {"to_str1"=>"45", "to_str2"=>"true"}
- 他にもキャスト(型変換)の方法はあるが詳しくは文末のリンクを参照されたい
yamlでの改行表現のバリエーション
- yamlではテキストの改行は認識されずスペースに変換される
input.yml
doc:
aaa
bbb
ccc
#=> {"doc"=>"aaa bbb ccc"}
- 改行を認識させる方法は二種類ある
- 大なり(
>
)を用いて文章最後の改行のみを認識させる方法
input.yml
doc: >
aaa
bbb
ccc
#=> {"doc"=>"aaa bbb ccc\n"}
- パイプ(
|
)を用いて全ての改行を認識させる方法 - これらの文法はマッピングだけでなくシーケンスでも使える
input.yml
doc: |
aaa
bbb
ccc
#=> {"doc1"=>"aaa\nbbb\nccc\n"}
- |
aaa
bbb
ccc
#=> ["aaa\nbbb\nccc"]
yamlでの複数データ構造の併記方法
- 複数データの区切りを表す方法は二種類ある
- 例えば複数のシーケンスが意図せずひとつなぎになってしまう時に使える
input.yml
- d1
- d2
- d3
- x1
- x2
#=> ["d1", "d2", "d3", "x1", "x2"]
- ピリオド×3つ(
...
)を使用して以降の読み込みを中止する場合 - デバッグ等で以降の操作を一時的に取りやめたいときに便利
input.yml
- d1
- d2
- d3
...
- x1
- x2
#=> ["d1", "d2", "d3"]
- ハイフン×3つ(
---
)を使用してデータ区切りを示す場合 - 複数のデータのまとまりをつくることができる
- 複数のデータを読み込む際には呼び出し方法が若干異なる
- yamlのデータであることを示すために先頭に(
---
)を付与することもある
output.rb
File.open('input.yml') do |io|
YAML.load_documents(io) do |d|
p d
end
end
input.yml
−−−
- d1
- d2
- d3
---
- x1
- x2
#=>
["d1", "d2", "d3"]
["x1", "x2"]
【アペンディックス】
- もっと実践的な知識がほしいよ、という方はこちら
- 参考リンク「Rubyist Magazine: プログラマのためのYAML入門」