YAMLでnilをキーにしたハッシュを扱う

例は全てRuby 2.0を利用しています

nilをキーとした値を持つハッシュをYAMLに書きたい場合、
以下のように書いても"nil"という文字列として認識されます。

---
nil : nil

=> {"nil"=>"nil"}

データがnilの場合は、データ部分に何も書かないことでnilを表現できます。

---
datanil :

=> {"datanil"=>nil}

キーをnilにしたい場合、以下のように書いても、(Rubyだと)パースに失敗します。

---
  : "key nil"

このような場合もYAMLの仕様では想定済みらしく、
クエッションマークを使うことで、その後ろにあるものがキーであると明示できる仕様があります。
http://yaml.org/spec/1.2/spec.html#id2772075

これを利用して、以下のようにクエッションマークの後に何も書かず、
その後コロンと値を設定することで、nilをキーとして設定できます。

---
?
: "key nil"

rubyで長い文字列をキーにする

Rubyが利用しているPsychでは、以下のように128byte以上のデータをキーにして書き出した場合、
?マークをつけて書き出します。

require 'yaml'
def mkhash(k,v)
  h = {}
  h[k] = v
  h
end

long = "a" * 129
open("long.yml", "w") {|file|
  file.write YAML.dump(mkhash(long, "long"))
}
---
? aaaaaaaaaaaaaaaaaaaaaaaaaa...aaa
: long

どうやらRubyが使っているYAMLライブラリのPsych内で、
128文字以上だったら?マークを出力するようにしているみたいです。

https://github.com/tenderlove/psych/blob/7e7ccf6fa4ee084c673d5a52888e2e18a41bfb5b/ext/psych/yaml/emitter.c#L816 https://github.com/tenderlove/psych/blob/7e7ccf6fa4ee084c673d5a52888e2e18a41bfb5b/ext/psych/yaml/emitter.c#L1168

一応YAMLの仕様としては1024文字までは?を使わなくてもいいらしいですが、何故128byteで切ってるのかは謎です。 http://yaml.org/spec/1.2/spec.html#id2792501

なお読み込む際は、クエッションマークをつけずに128byte以上のキーを指定しても問題なく読み込めます。