JSONにケツカンマを求めるのは間違っているだろうか

間違っています。JSONは仕様が簡潔で融通が利かないところがメリットであり、ケツカンマやコメントを許容しないこともそれに一役買っています。ケツカンマやコメントが欲しければYAMLを使いましょう。YAMLはJSONのスーパーセットなので、JSONにケツカンマやコメントをつければYAMLとして読むことは出来ます。

JSONとYAMLにはそれぞれに良さがあり、それぞれの良さを他方に求めると、その価値を毀損します。言ってしまえば、JSONはシンプルでありYAMLはイージーなのです。

参考: Simple Made Easy

JSONはシンプル

ご存知の通り、JSONはルールや覚えることが少ない反面、表現力に乏しいです。結果として人間にも機械にも比較的優しいシリアライゼーションフォーマットとして優れています。「ひとつのことをうまくやる」です。必ず1行に圧縮できる強みもあり、ログフォーマットとしても使いやすいです。コメントを許容してしまうと、それができなくなります。

RFC 8259 / ECMA-404 で仕様が厳密に定義されており、パーズもそれほど難しくありません。その分相互運用性が高く、システムを跨いだAPI等で世界中で使われています。つまり、ある言語のあるライブラリで書き出されたJSONが、他の言語のクライアントで必ず読めるということです。当たり前になっていますが、これは凄いことです。YAMLではそうはいきませんし、他の汎用ファイルフォーマットでもアプリケーションによって微妙に互換性が乏しくなることは珍しくありません。独自拡張してしまった結果、他のアプリケーションでは開けない、ということがままあります。

「ケツカンマくらい良いじゃないか」と思うかも知れませんが、ケツカンマを許容するということは、世界中の全てのパーザーにその処理を実装してもらう必要があると言うことです。もはや現実的にそれは不可能です。それに、ケツカンマを許容すると、パーズ時にバックトラックが発生し得る為、パフォーマンス劣化に繋がりますし、その為の処理分岐を追加する必要もあります。

JSONは世界中のAPIコールで常に使われているシリアライゼーションフォーマットであり、世の中のサーバーはかなりの割合JSONの処理に費やしています。ですから、パーズの難易度が高くなく、省リソースで処理できることが望ましいのです。そうしないと、バグが生まれやすくなりますし、ケツカンマを許容しただけでも世界中の電力消費がかなり増えてしまうでしょう。

勿論、パフォーマンスだけを考えたときにJSONが最適なデータフォーマットではないのは事実です。そもそもテキストフォーマットですし、カッコの対応や入れ子構造を処理する必要があります。なので、冒頭に述べた通り、人間にも機械にも比較的優しいシリアライゼーションフォーマットとして広く受け入れられたということです。

また、例えば、JSONではオブジェクトのキーのクオートが必須なのも面倒に感じますが、省略を許容したとしても、キー文字列の中にコロンが含まれていたらクオートしないといけません。そう言った余計なルールをケアしないといけなくなるのはライブラリ側に優しくありません。オブジェクトのキーをダブルクオート文字列と同じルールでパーズ出来ることがライブラリ側の実装を楽にしているのです。

結局、既に表現可能なデータ構造に対して、別の方法で表現可能にするシンタックスシュガーを追加することはJSONには求められてないですし、追加すると混乱を招くでしょう。JSONは完成されています。

YAMLはイージー

YAMLは覚えることは多いですが、表現力が豊かで、人間に読み書きしやすい(ように一見思えます)。多くのシンタックスシュガーが存在します。一般人にJSONとYAMLを同時に見せたら、YAMLのほうが取っつきやすいように見えるでしょう。

見様見まねで書く分にはJSONより書きやすく、タイプ数も少ないです。なので、設定ファイルでよく利用されます。設定ファイルであれば、そのファイルをそのアプリケーションで読めれば良い為、システムを跨いだ相互運用性を気にする必要はありません。

しかし、YAMLは仕様が複雑で難解です。YAMLの仕様を完全に満たした実用的なパーザーは世に存在しません。仕様自体への疑義もありYAML公式も仕様の準拠にこだわっていないという見解が述べられることもあります。

参考: gopkg.in/yaml のアーカイブと乗換先やメンテナンス継承議論 | おそらくはそれさえも平凡な日々

例えば、YAMLは仕様上文字列以外をオブジェクトのキーにできます。オブジェクトや配列もオブジェクトのキーにできるのです。{foo: bar}: hoge は仕様上正しいYAMLです。ただ、それをちゃんとパーズできるライブラリは少ないでしょうし、それを本当に実装する必要があるかどうかという話もあるでしょう。

アンカー記法も複雑です。例えば、エイリアスでアンカーで既に定義されているキーを定義した場合、それが上書きされるかキー重複エラーになるかは、YAML1.2の仕様には明記されていません。その為、ライブラリによって挙動が異なります。

つまり、あるライブラリで書かれたYAMLが他のライブラリで読めるとは限らないのです。これでは設定ファイルならともかくAPIコールで使うような汎用のシリアライゼーションフォーマットとしては使い物になりません。

YAMLは色々やり過ぎですし、思うところはありますが、受け入れざるを得ないものになっているとは思います。JSONを新たに拡張するなどして、よりよいフォーマットを作る試みもあり、一定の成功を収めているものもありますが、新たな「オレオレ」が増えただけという感じもします。

YAMLのルーツとIngy döt Net氏

ところで、YAMLのルーツは、Ingy döt Net氏によって作られた、Data::Denter というPerlモジュールです。XMLの簡素化を目指すsml-devグループのClark EvansとOren Ben-Kikiと合流してプロジェクトが始まったと、https://yaml.org/about で述べられています。

Ingy döt Netさんは今でもYAML仕様のprimary maintainer / managerを務めています。この、Ingy döt Netという名前は本名です。2006年の9月に法的に改名したことやその時のエピソードがYAPC::Asia 2007の発表の中で語られています。

www.youtube.com

それくらい、ぶっ飛んだ人です。この人はもちろんスゴイハッカーではありますが、界隈の面白枠の人でもありました。コンセプトメーカーで発明家であり、不思議なソフトウェアを作る人です。Perlのマジカルさを好む人で、彼の作る奇妙な作品群は、本気なのか冗談なのか判断に付きかねるものも多くあります。それが彼の味であり、そして、何れも鋭い視点のアイデアに根ざしています。

とは言え、コンセプトやアイデアはとても素晴らしいのですが、その哲学が独特であるため、多くの人に長く受け入れられるようなものにはなりにくい作家性があります。YAMLからもその香りを感じます。しかし、YAMLは何故か広く受け入れられるようになりました。「何故、世界はIngyのコンセプトを真に受けてしまったのか…」と思ってしまうこともあります。

そんなIngyさんが現在アクティブに大真面目に取り組んでいるプロジェクトがYAMLScriptです。GitHub冒頭の説明に "Program in YAML"と書かれていて嫌な予感がします。とても彼らしくて面白いと思います。