YAML と同じような軽量マークアップ言語に JSON(JavaScript Object Notation)があります。こちらは、YAMLのように人間に読みやすいデータ記述をねらったと言うよりは、複数のプログラム言語間で構造化したデータをやりとりするときのデータ交換言語をめざしているようです。ところが、この仕様書をみると分かるように Ruby でオブジェクトを記述するときのやり方とほとんど同じです。ただ一ヶ所ハッシュのペアを表すのに Ruby で => が使われているところが : になっているだけなのです。実際、RubyForgeにはたった一行のjason parser が紹介されています。
null=nil;jsonobj=eval(json.gsub(/(["'])\s*:\s*(["'0-9tfn\[{](/){"#{S1}=>#{S2}"})
また、JSON では YAML の場合とは違ってインデントに意味を持たせてはいませんが、JSON Exampleではインデントを活用することで XML よりはるかに可読性が良くなることを示してあります。
Ruby 用の JSON のライブラリの開発も始まっているようですし、JSONを使えば問題はないようにも思えますが、JSON もまた、多バイト文字のエンコーディングは UTF で、EUC が使えないようなのです。
そこで、Ruby のオブジェクトの記述を、インデントして可読性を高めて印字するプログラムを作ってみました。Object メソッドのインスタンス・メソッドとして定義したので、obj.to_ron とすると打ち出してくれます。Rubyによるオブジェクトの記述をJSONをもじって、RON(Ruby Object Notation)と勝手に呼ぶことにしました。オブジェクトから RON を出力するプログラム ron.rb は次のようになります。ライブラリなので、require 'ron' で使います。
class Object def to_ron str = self.inspect lines = str.gsub(/\{/, "{\n").gsub(/\[/, "[\n").gsub(/\,\s*/, ",\n").to_a indent = 0 lines.collect! do |line| line.sub!(/^/, " " * indent) case line when /[\[\{]$/ indent += 4 else if line =~ /([\]\}]+).*$/ indent -= 4 * $1.size end end line end lines.join end end
irb で試した結果を次に示します。inspect の結果とくらべても、随分可読性が上がったようです。
$ irb irb(main):001:0> require 'ron' => true irb(main):002:0> a = {"apple"=>"red", "orange"=>"orange", "vegitables"=> irb(main):003:1* ["onion", "cabbage", "raddish"], "lemon"=>"yellow"} => {"vegitables"=>["onion", "cabbage", "raddish"], "apple"=>"red", "orange"=>"orange", "lemon"=>"yellow"} irb(main):004:0> puts a.to_ron { "vegitables"=>[ "onion", "cabbage", "raddish"], "apple"=>"red", "orange"=>"orange", "lemon"=>"yellow"} => nil
YAML.load に相当するメソッドはありません。a = eval(ron_string) 一発でオブジェクトに変換できるからです。
実行結果からも分かるようにオブジェクトを作成するときと、to_ron の出力では、ハッシュのペアの順番が変ってしまいます。この事情は YAML でも一緒です。定型的なフォーマットで入出力を行うためには出力は puts 関数を使ってペアの順序が変らないようにしたほうが良いようです。
そう考えると YAML や JSON が UTF しかサポートしなくても、少なくとも読みこむときにエンコーディングの変換をせずにそのまま取りこんでくれれば、日本語 EUC を使って障害なく読み書きすることができます。