今回は、
Syck
Syckは、
Webサイト | http:// |
---|---|
ドキュメント | http:// index. |
バージョン | 0. |
作者 | why the lucky stiff |
インストール
Ruby 1.
使い方
Syckの使い方はリスト1のとおりです。詳細はリファレンスマニュアル
require 'yaml'
## YAMLドキュメントを読み込む
str = File.read('example.yaml')
data = YAML.load(str) # 引数は文字列またはI/O
data = YAML.load_file('example.yaml') # 引数はファイル名
## YAMLストリームを読み込む
File.open('example.yaml') do |f|
YAML.load_documents(f) do |data| # 引数は文字列またはI/O
# ...
end
end
## 任意のデータをYAML文字列に変換する
data = [ {'x'=>10, 'y'=>20}, {'x'=>15, 'y'=>25} ]
str = data.to_yaml
## または
## str = YAML.dump(data) # 任意のデータをYAML文字列に変換する
## y data # 任意のデータをYAML文字列に変換して出力する
タグを変更する
yaml.
これを回避するには、
- Object#taguri()
- オブジェクトを表すタグを返します。
- YAML.
add_ builtin_ type(ytag) {|type, val| ...} - データからオブジェクトを復元するブロックを登録します。
またObject#to_
require 'yaml'
class Color
def initialize(r, g, b)
@r = r; @g = g; @b = b
end
attr_accessor :r, :g, :b
## タグを「!ruby/object:Color」から「!color」へ変更する
def taguri
return 'tag:yaml.org,2002:color' # !color
#return 'x-private:color' # !!color
end
## フロースタイルで表示する
def to_yaml_style
return :inline
end
end
## 実行例
obj = Color.new(255, 128, 0)
puts YAML.dump(obj) #=> --- !color {b: 0, g: 128, r: 255}
## 「!color」タグのときにColorオブジェクトを生成する
YAML.add_builtin_type('color') do |type, val|
YAML.object_maker(Color, val)
end
## 「!!color」タグのときにColorオブジェクトを生成する
#YAML.add_private_type('color') do |type, val|
# YAML.object_maker(Color, val)
#end
## 実行例
str = '!color {r: 255, g: 128, b: 0}'
p YAML.load(str) #=> #<Color:0x5da9e4 @b=0, @g=128, @r=255>
日本語の扱い
Rubyの文字列に日本語が含まれる場合、
しかしこれは不便である人も多いでしょう。この回避策としては、
--- ruby-1.8.6-p111/ext/syck/emitter.c Wed Jan 09 12:57:49 2008 +0900
+++ ruby-1.8.6-p111/ext/syck/emitter.c Wed Jan 09 14:07:38 2008 +0900
@@ -778,7 +778,8 @@ syck_emitter_escape( SyckEmitter *e, cha
int i;
for( i = 0; i < len; i++ )
{
- if( (src[i] < 0x20) || (0x7E < src[i]) )
+ /*if( (src[i] < 0x20) || (0x7E < src[i]) )*/
+ if( 0 )
{
syck_emitter_write( e, "\\", 1 );
if( '\0' == src[i] )
.--------------------
require 'yaml'
class String
def is_binary_data?
false ## 日本語がバイナリとみなされるのを防ぐ
end
end
puts YAML.dump(['alphabet', '日本語'])
### 実行結果:
## ---
## - alphabet
## - "日本語"
もう1つの方法は、
ただし、
## 日本語文字列は、バイナリデータとして扱われてしまう
str = 'いろは'
require 'yaml'
p str.to_yaml #=> "--- !binary |\n44GE44KN44Gv\n\n"
## ya2yamlを使うと、UTF8の文字列はそのまま出力される
require 'rubygems' # RubyGemsでインストールした場合
require 'ya2yaml'
$KCODE = 'utf8'
p str.ya2yaml #=> "--- いろは\n"
## Object#to_yamlをya2yamlで置き換えてもよい
[Object, String, Array, Hash].each do |klass|
klass.class_eval { alias to_yaml ya2yaml }
end
p str.to_yaml #=> "--- いろは\n"
不具合
筆者が試したところ、
日付
対応するアンカーのないエイリアスがあっても、
フロースタイルのデータにエイリアスをつけるとエラーになる場合がある
- 2008-01-01T12:34:56Z
- 2008-01-01 12:34:56
- 2008-01-01 12:34:56Z
- 2008-01-01T12:34:56
- 2008-01-01 12:34:56 +9
- 2008-01-01 12:34:56.0
- &m1
{a: 10}
- &s1
Foo
その他
Syckは、
- 「:foo」
のようなデータは、 文字列ではなくRubyのSymbolオブジェクトに変換されます。
RbYAML
RbYAMLは、
Syckとの最大の違いは、
ただし、
Webサイト | http:// |
---|---|
ダウンロード | http:// |
ドキュメント | なし |
バージョン | 0. |
作者 | Ola Bini |
インストール
RubyGemsをインストールしてから
使い方
使い方は、
require 'rubygems' # RubyGemsを使ってインストールした場合
require 'rbyaml'
## YAMLドキュメントを読み込む
str = File.read('example.yaml')
data = RbYAML.load(str) # 引数は文字列またはI/O
data = RbYAML.load_file('example.yaml') # 引数はファイル名
## YAMLストリームを読み込む
File.open('example.yaml') do |f|
RbYAML.load_documents(f) do |data| # 引数は文字列またはI/O
# ...
end
end
## 任意のデータをYAML文字列に変換する
data = [ {'x'=>10, 'y'=>20}, {'x'=>15, 'y'=>25} ]
str = data.to_yaml
## または
## str = RbYAML.dump(data) # 任意のデータをYAML文字列に変換する
## y data # 任意のデータをYAML文字列に変換して出力する
タグを変更する
RbYAML.
これを回避するには、
- Object.
to_ yaml_ node(representer) - オブジェクトをノード
(RbYAML::Node) に変換します。 - RbYAML._add_
constructor(ytag, symbol) - ノード
(RbYAML::Node) からオブジェクトを復元するメソッドをRbYAML::Constructorクラスに定義し、 そのメソッド名を登録します。
require 'rubygems'
require 'rbyaml'
## クラス定義
class Color
def initialize(r, g, b)
@r = r; @g = g; @b = b
end
attr_accessor :r, :g, :b
## タグを変更する
def to_yaml_node(representer)
node = super
node.tag = '!color' # 元は '!ruby/object:Color'
node.flow_style = true # flow styleで出力する
node
end
end
## 実行例
color = Color.new(255, 128, 0)
puts RbYAML.dump(color) #=> --- !color {r: 255, g: 128, b: 0}
## マッピングからColorオブジェクトを生成するメソッド
class RbYAML::Constructor
def construct_ruby_color(node)
return construct_ruby('Color', node)
end
end
## メソッド名を '!color' タグで登録する
RbYAML._add_constructor('!color', :construct_ruby_color)
## 実行例
obj = RbYAML.load('!color {r: 255, g: 128, b: 0}')
p obj #=> #<Color:0x531d1c @r=255, @b=0, @g=128>
日本語の扱い
日本語を含むYAMLドキュメントを読み込む場合、
書き出しについては、
不具合
RbYAMLは古いバージョンのPyYAMLをもとにしているためか、
- YAML.
load() - 循環構造を持つデータが解釈できない
- 値がない場合にエラーが発生する
(リスト10) - 文字列をブロックスタイルで記述したとき、
最終行の改行が取り除かれる (リスト11) - マッピングのデフォルト値を認識しない
「'foo\n'」 が 「"foo\n"」 ではなく 「"foo92n"」 になる
- YAML.
dump() - 循環構造を持つデータに対応していない
- abc
- # nullと解釈されるべきだがRbYAMLではエラー
- 123
## ["text\n"] となるはずが ["text"] となる
- |
text
その他
作者のOla Biniは、
Kwalify
Kwalifyは、
YAMLドキュメントのデータ構造を形式的に記述したものをスキーマといいます。そのスキーマ定義に従って、
Kwalifyは、
Webサイト | http:// |
---|---|
ドキュメント | http:// kwalify/ |
ダウンロード | http:// |
バージョン | 0. |
作者 | Makoto Kuwata |
インストール
RubyGemsをインストールしている場合は、
$ tar xjf kwalify_0.7.0.tar.bz2 $ cd kwalify_0.7.0 $ sudo ruby setup.rb install
使い方
KwalifyのYAMLパーサは、
require 'kwalify'
## スキーマ定義(詳細についてはドキュメントを参照)
schema_def = <<END
type: map
class: Config # データバインディングにはクラス名が必要
mapping:
"host": {type: str, default: localhost}
"port": {type: int, default: 80}
"user": {type: str, required: true}
"pass": {type: str, required: true}
END
## スキーマ定義に対応したクラス定義
## (メソッド '[]', '[]=', 'key?' の定義が必要。ここでは
## Kwalify::Util::HashLike を include することで、
## これらのメソッドを定義している。)
require 'kwalify/util/hashlike'
class Config
include Kwalify::Util::HashLike
def initialize
@host = 'localhost' # デフォルト値
@port = 8080 # デフォルト値
end
attr_accessor :host, :port, :user, :pass
end
## スキーマ定義から Validator オブジェクトを作る
schema = Kwalify::Yaml.load(schema_def)
validator = Kwalify::Validator.new(schema)
## パーサを作成する
parser = Kwalify::Yaml::Parser.new(validator)
parser.data_binding = true # データバインディングを有効化
## YAMLドキュメントをパースする
str = <<END
#host: localhost
port: 8080
user: user1
pass: password1
END
ydoc = parser.parse(str)
p ydoc
## 実行例
## (HashではなくConfigオブジェクトが生成されていることがわかる):
## #<Config:0x571df4 @pass="password1", @port=8080,
## @user="user1", @host="localhost">
## バリデーションエラーがあれば表示する
errors = parser.errors
if errors && !errors.empty?
for e in errors
puts "#{e.linenum}:#{e.column} [#{e.path}] #{e.message}"
end
end
Kwalifyでは、
またそのほかの機能として、
str = <<END
- &a1
val: 10
next: *a2 # アンカーより先にエイリアスが現れている
- &a2
val: 20
next: *a3 # アンカーより先にエイリアスが現れている
- &a3
val: 30
next: *a1
END
## Kwalify::Yaml.load() に :preceding_alias=>true を与えると、
## アンカーより先に現れたエイリアスも解釈してくれる。
require 'kwalify'
ydoc = Kwalify::Yaml.load(str, :preceding_alias=>true)
## または
## parser = Kwalify::Yaml::Parser()
## parser.peceding_alias = true
## ydoc = parser.parse(str)
## データを表示する
require 'pp'
pp ydoc
## 実行例:
## [{"val"=>10, "next"=>{"val"=>20, "next"=>{"val"=>30, "next"=>{...}}}},
## {"val"=>20, "next"=>{"val"=>30, "next"=>{"val"=>10, "next"=>{...}}}},
## {"val"=>30, "next"=>{"val"=>10, "next"=>{"val"=>20, "next"=>{...}}}}]
タグを変更する
KwalifyのYAMLパーサは、
日本語の扱い
日本語を含むYAMLドキュメントの読み込みについては、
不具合
以下のような不具合があります。
- タグに未対応
- オブジェクトをdumpする機能がない
- キーと同じインデント幅でシーケンスが続くとパースできない
(リスト14)
## {"key": [10, 20, 30]} と同じはずだが
## Kwalify ではエラーになる
key:
- 10
- 20
- 30
その他
KwalifyのYAMLパーサは、
しかしスキーマバリデーションやデータバインディングは大変便利な機能です。またアンカーより先にエイリアスを書ける機能も、
またKwalifyのスキーマバリデーションやデータバインディングは、