JSYNC=JSON+YAML(参照と型宣言に対応したJSON拡張仕様案)

YAML メンバーの1人、Ingy döt Net の新プロジェクト JSYNC (JavaScript and YAML Notation Coding) のご紹介です。JSYNC は、JSON に YAML の一部機能を組み入れたデータシリアライズの新しい仕様です。
(YAML 復習)
これまで僕が YAML を使うときは、JSON みたいな単純なハッシュ・配列のシリアライズにしか使っていなかったけど、YAML の仕様では、以前から、参照を実現する アンカー anchor (&)とエイリアス alias (*) の機能や、型宣言を実現するタグ tag (!) の機能があったのですね。
タグによる型宣言
まず、タグ (!) を使ったプリミティブ型の型宣言を見てみます。入力する YAML:
---
number: !!int 1
string: !!str 1
Perl デコード結果:
$VAR1 = {
'number' => 1,
'string' => '1'
};
!!int を付けた値が文字列でなくて、数値になっています。
なお、YAML::XS を使うと、現在は下記のエラーが出るようです。
バグだそうなので、そのうち直るのかと。
YAML::XS Error: bad tag found for scalar: 'tag:yaml.org,2002:str' at /Library/Perl/5.10.0/YAML/Any.pm line 81, <FIN> line 4.
ysh を使う場合は、デフォルトの YAML::XS でなく、YAML::Syck を使ってください。
$ ysh -MYAML::Syck
その他の type は、こちら に載っています。
全ての機能が実装されているわけではないみたい。
独自の tag を使用することで、任意のオブジェクトのインスタンスも受け渡しできる。
アンカー+エイリアスによる参照
入力する YAML:
---
foo: &hoge
- 1
- 2
bar: *hoge
Perl デコード結果:
$VAR1 = {
'bar' => [
1,
2
],
'foo' => $VAR1->{'bar'}
};
HTML の name="hoge" のように、&hoge でアンカーを定義して、
また、href="#hoge" のように、*hoge で呼び出して参照しています。
こちらは、YAML::XS、YAML::Syck どちらでも動きます。
また、循環参照も記述できるので、実際に使う場合はメモリリークに注意。
JSYNC = YAML 仕様の JSON への応用
これらの、! タグ、& アンカー、* エイリアスの仕組みを
JSON に応用するという提案が、JSYNC になります。
使用例:
[
"!records", /* この配列の型宣言 records 型 */
{
"!": "record", /* このハッシュの型宣言 record 型 */
"game": {
"!": "game", /* このハッシュの型宣言 game 型 */
"&": "001", /* アンカーの定義 001 */
"date": "!!date March 2, 1962", /* 日付型 */
"versus": "New York"
},
"notes": ".!!! Awesome !!!", /* 先頭の『!』エスケープ */
"number": 100,
"player": {
"!": "player", /* このハッシュの型宣言 player 型 */
"&": "002", /* アンカーの定義 001 */
"name": "Wilt Chamberlain",
"team": "Philadelphia"
},
"record": "Most points single game"
},
{
"!": "record", /* このハッシュの型宣言 record 型 */
"game": "*001", /* game 001 を参照する */
"notes": ".... add note here ...", /* 先頭の『.』エスケープ */
"number": 59,
"player": "*002", /* player 001 を参照する */
"record": "Most points, one half"
}
]
基本的に、JSON のデータ表現をそのままに、YAML の記法を導入して
タグ(型宣言)とアンカー・エイリアス(参照)の機能を提供する。
データ構造はそのまま JSON なので、既存の JSON パーサーでも、概ね読める。
型宣言は、プリミティブ型以外に、任意のオブジェクトのインスタンスも渡せる。
文字列冒頭に ! * & . の文字があれば、. でエスケープする。
まだ、実装は出ていないみたい。
もっと複雑なスキーマ定義用途としては、JSON Schema という仕様(ドラフト)も出ているが、
シンプルさがウリのはずの JSON が冗長で複雑な XML みたいになってしまっていて、
ちょっと難しい気がする。
バイナリ方面では、MessagePack はプリミティブ型以外は渡せないの?
この記事へのコメント