YAML::dump (syck) の出力の整形について
YAMLの復習
YAMLのノードには3種類(kind)がある:
- Scalar (Unicodeの文字列として表現できるもの)
- Sequence (配列みたいなもの)
- Mapping (連想配列やHashみたいなもの)
それぞれのkindはいくつかのstyleで出力できる。
- Scalar:
- Plain (1行)
yaml>>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<<-- - Single Quote (1行)
yaml>>
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
<<-- - Double Quote (1行)
yaml>>
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
<<-- - Block Literal (改行がそのまま残る)
yaml>> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque tincidunt molestie est. Vestibulum ante odio, euismod ac, sagittis et, tempus ut, lorem. Praesent consectetur tempor ipsum. Nulla facilisi. <<-- - Block Folding (改行が空白になる)
yaml>>
--- >
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Pellentesque tincidunt molestie est.
Vestibulum ante odio, euismod ac,
sagittis et, tempus ut, lorem.
Praesent consectetur tempor ipsum.
Nulla facilisi.
<<--
- Sequence
- デフォルト
yaml>>
- one
- two
- three
<<--
- inline
yaml>>
[1, 2, 3]
<<--
- Mapping
- デフォルト
yaml>>
height: 170
weight: 60
<<-- - inline
yaml>>
{ height: 170, weight: 60}
<<--
で、
YAML::dumpでオブジェクトをダンプしたい時、styleを統一する場合もある。が、YAML::dumpにはstyleを指定する機能はない。そこで、to_yaml_styleをオブジェクトに定義すればよい、という裏技(非ドキュメントメソッド)を紹介したい。このメソッドの返り値がそのオブジェクトのstyleになる。
例えば:
ruby>>
class String
def to_yaml_style
return :quote2
end
end
<<--
をすれば、YAML::dumpのすべての文字列がダブルクオートに囲まれる。
Rubyでのスタイルは以下:
ruby>>
:plain # クオートなし
:quote1 # シングルクオート
:quote2 # ダブルクオート
:literal # Block Literal
:fold # Block Folding
:inline # Inline (Sequence, Mapping)
nil # デフォルト (Sequence, Mapping)
<<--
ちなみに、これを調べた切っ掛けはHashをYAML::dumpした時にvalueの方にクオートがあったりなかったりしたからです。つまりこれ:
yaml>>
name: "鈴木"
height: 170
weight: 60
<<--
をこれにする:
yaml>>
name: "鈴木"
height: "170"
weight: "60"
<<--
monkeypatch的な解決方法:
ruby>>
class Hash
def to_yaml_with_quoted_strings(*args)
class << self
unless method_defined?(:each_with_quoted_strings)
def each_with_quoted_strings
each_with_normal_strings do |k,v|
if String === v && !v.frozen?
def v.to_yaml_style; return :quote2; end
end
yield k, v
end
end
alias_method :each_with_normal_strings, :each
alias_method :each, :each_with_quoted_strings
end
end
return to_yaml_with_normal_strings(*args)
end
alias_method :to_yaml_with_normal_strings, :to_yaml
alias_method :to_yaml, :to_yaml_with_quoted_strings
end
<<--
参考
- YAMLの仕様
- _why on to_yaml_style@ruby-talk:178321
- syck on github
- syck.h styleの定義
- rubyext.c styleのRubyマッピング