Kwalifyの3つのライブラリを紹介します。
Syck
Syckは、Cで書かれたYAML用ライブラリです。YAML用ライブラリとしては世界で最も広く使われており、YAMLの普及に大きく貢献しました。
インストール
Ruby 1.8以上であれば標準で付属しているため、インストールの必要はありません。
使い方
Syckの使い方はリスト1のとおりです。詳細はリファレンスマニュアル[1]をご覧ください。
タグを変更する
yaml.dump()でインスタンスオブジェクトをYAML文字列に変換した場合、たとえば「!ruby/object:Color」のようなタグがつきます。しかしこれだとRuby限定になり、ほかの言語のYAMLパーサで読み込むとエラーになるため、データ交換する場合には都合が悪いです。
これを回避するには、以下のメソッドを使ってクラスに対応するタグを指定します(リスト2)。
- Object#taguri()
- オブジェクトを表すタグを返します。
- YAML.add_builtin_type(ytag) {|type, val| ...}
- データからオブジェクトを復元するブロックを登録します。
またObject#to_yaml_style()を再定義することで、フロースタイルで出力させることができます。
日本語の扱い
Rubyの文字列に日本語が含まれる場合、YAMLドキュメントに変換すると、たとえば「'いろは'」が「!binary 44GE44KN44Gv」のようにバイナリデータとして変換されてしまいます。この問題は、根本的にはRubyにおいて文字列とバイナリデータの区別がないことが原因であり、そのためにSyckは安全を期して「ASCII以外の文字を(ある一定の比率で)含むような文字列はバイナリデータ」とみなしています。
しかしこれは不便である人も多いでしょう。この回避策としては、2つあります。1つ目はSyckのソースコードにパッチを当てることです。Rubyのソースコードをダウンロードし、リスト3のパッチを適用してコンパイルします。そしてリスト4のようString#is_binary_data?()を上書きしてバイナリとみなされないようにすると、日本語文字列が二重引用符で囲まれて出力されるようになります。
もう1つの方法は、Ya2YAMLを使うことです。Ya2YAMLをインストールして$KCODEを'utf8'に設定すると、文字列をUTF8として扱ってくれます(リスト5)。Ya2YAMLはRubyGemsを使って「gem install ya2yaml」とすればインストールできます。
ただし、循環参照したデータには対応していません。
不具合
筆者が試したところ、以下のような不具合がありました(Ruby 1.8.6で確認)。
日付(タイムスタンプ)の解析に不具合があり、「2008-01-01T12:34:56Z」という形式しか解釈されない(リスト6)。
対応するアンカーのないエイリアスがあっても、エラーにならない。
フロースタイルのデータにエイリアスをつけるとエラーになる場合がある(リスト7)。
その他
Syckは、Ruby向けに次のような独自機能を実装しています。
- 「:foo」のようなデータは、文字列ではなくRubyのSymbolオブジェクトに変換されます。
RbYAML
RbYAMLは、pure Rubyで実装されたYAMLライブラリです。もともとは、Syckが拡張ライブラリであるためJRubyで使えないので、JRubyでも使えるようなPure RubyのYAMLライブラリが必要だったために開発されました[3]。またRbYAMLは、Python用のライブラリであるPyYAMLをRubyに移植したものです。
Syckとの最大の違いは、SyckがYAML 1.0準拠なのに対し、RbYAMLはYAML 1.1準拠だという点です。そのため、SyckとRbYAMLとでは仕様が異なる点があります。
ただし、循環したデータ構造が扱えないなど、Syckと比べて不具合が多いです。
インストール
RubyGemsをインストールしてから「gem install rbyaml」でインストールしてください。
使い方
使い方は、クラス名がYAMLでなくRbYAMLとなっている点以外はSyckとほぼ同じです(リスト8)。
タグを変更する
RbYAML.dump()でインスタンスオブジェクトをYAML文字列に変換した場合、たとえば「!ruby/object:Color」のようなタグがつきます。しかしこれだとRuby限定になり、ほかの言語のYAMLパーサで読み込むとエラーになるため、データ交換する場合には都合が悪いです。
これを回避するには、以下のメソッドを使ってクラスに対応するタグを指定します(リスト9)。
- Object.to_yaml_node(representer)
- オブジェクトをノード(RbYAML::Node)に変換します。
- RbYAML._add_constructor(ytag, symbol)
- ノード(RbYAML::Node)からオブジェクトを復元するメソッドをRbYAML::Constructorクラスに定義し、そのメソッド名を登録します。
日本語の扱い
日本語を含むYAMLドキュメントを読み込む場合、RbYAML.load()の引数に文字列を指定した場合は問題なく読み込めますが、FileオブジェクトやIOオブジェクトを指定するとエラーになります。
書き出しについては、たとえば「'いろは'」が「!!binary 44GE44KN44Gv」のようにバイナリデータとして出力されてしまいます。これを回避する方法は、現状では提供されていません。
不具合
RbYAMLは古いバージョンのPyYAMLをもとにしているためか、いろいろとバグや制限が多いです。筆者が試したところ、以下のようなバグや制限が見つかりました。
- YAML.load()
- 循環構造を持つデータが解釈できない
- 値がない場合にエラーが発生する(リスト10)
- 文字列をブロックスタイルで記述したとき、最終行の改行が取り除かれる(リスト11)
- マッピングのデフォルト値を認識しない
- 「'foo\n'」が「"foo\n"」ではなく「"foo92n"」になる
- YAML.dump()
その他
作者のOla Biniは、現在はJRubyで忙しく、RbYAMLは放置気味です。そのため、RbYAMLの不具合が修正される可能性は低いでしょう。
Kwalify
Kwalifyは、YAML用のパーサ、スキーマバリデータ、データバインディングが統合されたライブラリです。
YAMLドキュメントのデータ構造を形式的に記述したものをスキーマといいます。そのスキーマ定義に従って、YAMLドキュメントのデータが正しい構造かどうかをチェックすることをスキーマバリデーションといい、それを実行するツールをスキーマバリデータといいます。またYAMLドキュメントのデータは、通常は(Rubyであれば)HashやArrayなどに変換されますが、それらのかわりにユーザが指定したクラスのオブジェクトに変換するのをデータバインディングといいます。
Kwalifyは、これらが統合されたライブラリです。Kwalifyを使うと、YAMLドキュメントをパースするときに、スキーマバリデーションとデータバインディングを同時に行うことができます。
インストール
RubyGemsをインストールしている場合は、「gem install kwalify」でインストールできます。RubyGemsをインストールしていない場合は、以下の手順でインストールしてください。
使い方
KwalifyのYAMLパーサは、スキーマ定義を与えることで、パースしながらスキーマバリデーションとデータバインディングを同時に行うことができます(リスト12)。スキーマ定義などの詳細についてはドキュメントを参照してください。
Kwalifyでは、スキーマ定義からRubyのクラス定義を生成する機能もあります。詳しくはドキュメントを参照してください。
またそのほかの機能として、KwalifyのYAMLパーサではアンカーより先にエイリアスを書くことができます(リスト13)。これは、参照構造が複雑なデータを記述するときに大変便利です。
タグを変更する
KwalifyのYAMLパーサは、タグに対応していません。
日本語の扱い
日本語を含むYAMLドキュメントの読み込みについては、問題ありません。書き出しについては、Kwalifyはデータをdumpする機能はありません。
不具合
以下のような不具合があります。
- タグに未対応
- オブジェクトをdumpする機能がない
- キーと同じインデント幅でシーケンスが続くとパースできない(リスト14)
その他
KwalifyのYAMLパーサは、よく使われる機能だけを実装しており、あまり使われない機能は実装されていません。よってデータ交換を目的とするなら、あまり使うべきではないでしょう。
しかしスキーマバリデーションやデータバインディングは大変便利な機能です。またアンカーより先にエイリアスを書ける機能も、複雑なデータ構造を記述する場合には実に重宝します。このため、データ交換には向きませんが、設定ファイルやデータファイルを読み込むときに使うとよいでしょう。
またKwalifyのスキーマバリデーションやデータバインディングは、YAMLだけでなくJSONにも活用できます。これは、JSONがYAMLのサブセットと見なせるためです。興味のある人は試してみてください。