JSONより出来の良い妹「SION」
今回はSION というデータシリアライゼーションフォーマット(data serialization format)を提案します。
Wh(at|y)Serialization?
その前にシリアライゼーション(serialization)とは何かを復習しておきましょう。「 シリアライズ(serialize)すること?」正解です。では、シリアライズとは何? 文字入力を音声入力する(siri)ではありません:-)。プログラムの中のオブジェクト(objects)をバイト列(bytes)に変換することです。実質すべてのプログラムは入力されたバイト列をデシリアライズ(deserialize)し、処理した結果をバイト列で出力、つまりシリアライズしているわけで、それをどのような形式=フォーマットで行うかというのはコード(codes)以上に重要な課題と言えましょう。mp4は動画をシリアライズするためのフォーマットですし、JPEGやpngは静止画像をシリアライズするためのフォーマットですが、一般にシリアライゼーションフォーマットといった場合は特定のデータではなく汎用的にデータをシリアライズするものを指し、本記事でもその意味でこの言葉を用いることにします。
汎用シリアライゼーションフォーマットには大きく分けて2つの目的があります。
データ交換(data exchange)
データ可視化(data visialization)
うち前者に関しては、多くの言語がその言語専用のシリアライゼーションフォーマットを持っています。PerlならStorable
、RubyならMarshal
、PythonならPickle
といった具合に。これらはいずれもバイナリフォーマット(binary for mats)で、人が直接読むのには不向きです。よって後者の目的のためのフォーマットが必要なのですが、よく見るものとしてはYAML が挙げられるでしょう。次はYAMLでシリアライズしたデータの例です。
YAML、XML、and JSON
リスト1 にYAMLの例を挙げます。とても直感的で人の手で読み書きするのも楽なので、Travis をはじめ、あちこちで設定ファイル(configuration files)として用いられています。
リスト1 YAMLの例
array:
- ̃
- true
- 1
- 0x1p+0
- one
-
- 1
-
one: 1.0
bool: true
dictionary:
array: []
bool: false
double: 0.0
int: 0
nil: ̃
object: {}
string:
double: 42.195
int: -42
nil: ̃
string: 漢字、カタカナ、ひらがなの入った"string"😇
url: https://github.com/dankogai/
一時期はXMLがその目的で流行ったことがありました。macOSになる前のMac OS Xでもかつては設定ファイルがXMLでした(リスト2 ) 。
リスト2 XMLの例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>array</key>
<array>
<true/>
<integer>1</integer>
<real>1</real>
<string>one</string>
<array>
<integer>1</integer>
</array>
<dict>
<key>one</key>
<real>1</real>
</dict>
</array>
<key>bool</key>
<true/>
<key>date</key>
<real>0.0</real>
<key>dictionary</key>
<dict>
<key>array</key>
<array/>
<key>bool</key>
<false/>
<key>double</key>
<real>0.0</real>
<key>int</key>
<integer>0</integer>
<key>object</key>
<dict/>
<key>string</key>
<string></string>
</dict>
<key>double</key>
<real>42.195</real>
<key>int</key>
<integer>-42</integer>
<key>string</key>
<string>漢字、カタカナ、ひらがなの入った"string"😇</string>
<key>url</key>
<string>https://github.com/dankogai/</string>
</dict>
</plist>
しかしデシリアライズが、あまりに重いうえにかさばり過ぎということで、Mac OS X v10.2以降ではバイナリフォーマットに切り替わりました。
このようにシリアライゼーションフォーマットはいくつもありますが、現在圧倒的に用いられているのはJSON で間違いないでしょう(リスト3 ) 。
リスト3 JSONの例
"array" : [
null,
true,
1,
1.0,
"one",
[1],
{"one" : 1.0}
],
"bool" : true,
"date" : 0.0,
"dictionary" : {
"array" : [],
"bool" : false,
"double" : 0.0,
"int" : 0,
"nil" : null,
"object" : {},
"string" : ""
},
"double" : 42.195,
"int" : -42,
"nil" : null,
"string" : "漢字、カタカナ、ひらがなの入った\"string\ "😇",
"url" : "https://github.com/dankogai/"
}
ECMAScriptのリテラル、つまりプログラマが書きおろすフォーマットがもとになっていることもあって、インデントと改行を入れれば人が読み書きするのも容易で、空白文字を取ればXMLよりもコンパクト。データ交換にも可視化にも向いたJSONは、今やECMAScriptだけではなくほとんどの言語で標準サポートしています。
しかし時代が経つにつれ、次のようにJSONに対する不満も溜まってきました。
コメント(comment)が使えない。設定ファイルとして使う場合、これはかなり不便[1]
辞書(dictionary) 、ECMAScriptでいうところのobjectのキーとして文字列(string)しか使えない[2]
Date
やData
がサポートされていない
MessagePack はバイナリフォーマットに特化することでJSONの不満をかなり解消しました。数値型はずっとコンパクトで、辞書のキーにはMessagePack自体でシリアライズできるデータはなんでも使える。しかしバイナリフォーマットだけあって人が直接読み書きするのは無理ゲー……。
――というわけで筆者は「テキスト版のMessagePack」を探していたのですが、ある日気づいてしまったのです。「 それってSwiftのリテラルでよくね?」と。
そうしてSIONが爆誕しました。
ご覧のとおり(表1 、リスト4 ) 、
辞書は{}
ではなく[]
で括る。空の辞書は[:]
とすることで配列[]
と区別しているのはSwiftと同様
コメント可能。//
から改行までがコメント
Data
とDate
も扱える
数値はInt
とDouble
を別のものとして扱う
→ Double
はNaN
も±Infinity
も受け付ける
→ 16進表記も受け付ける。これにより精度劣化が防げる
SION
で扱える型ならすべて辞書のキーとして使える
表1 SIONと他言語の比較
Type SION MsgPack JSON Property List Comment
Nil ✔ ✔ ✔ ✖ plist: .binary only
Bool ✔ ✔ ✔ ✔
Int ✔ ✔ ✖ ✔ 64bit
Double ✔ ✔ ✔ ✔ JSON's Number
String ✔ ✔ ✔ ✔ utf-8 encoded
Data ✔ ✔ ✖ ✔ binary blob
Date ✔ ✔ ✖ ✔ .timeIntervalSince1970 in Double
[Self] ✔ ✔ ✔ ✔ aka Array
[String:Self] ✔ ✔ ✔ ✔ aka Object, Map…
[Self:Self] ✔ ✔ ✖ ✖ non-String keys
リスト4 SIONの例
[
"array" : [
nil,
true,
1, // Int in decimal
1.0, // Double in decimal
"one",
[1],
["one" : 1.0]
],
"bool" : true,
"data" : .Data("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"),
"date" : .Date(0x0p+0),
"dictionary" : [
"array" : [],
"bool" : false,
"double" : 0x0p+0,
"int" : 0,
"nil" : nil,
"object" : [:],
"string" : ""
],
"double" : 0x1.518f5c28f5c29p+5, // Double in hexadecimal
"int" : -0x2a, // Int in hexadecimal
"nil" : nil,
"string" : "漢字、カタカナ、ひらがなの入ったstring😇,"
"url" : "https://github.com/dankogai/",
nil : "Unlike JSON and Property Lists,",
true : "Yes, SION",
1 : "does accept",
1.0 : "non-String keys.",
[] : "like",
[:] : "Map of ECMAScript."
]
JSONがJavaScript Object Notationなら、SIONはSwift Interchangeable Object Notation。読み方は「紫苑(シオン) 」でも「西園(サイオン) 」でも“ es-eye-oh-en” でもどれでもいいのですが、日本だと「紫苑」が多そうです。
幸いにして業界の評判は上々で(表1 のコメント欄参照) 、最初のリファレンス実装であるswift-sion をGitHubに上げて、Qiitaで紹介 したら、MessagePackの中の人も好意的に評価 してくださいましたし、本誌でもおなじみのVimmerでGopherなmattnがgo-sion を公開してくれました。それも筆者がECMA Scriptの実装、js-sion をあげる前に!
次回予告
というわけで、次回はこのSIONの実装であるswift-sionを題材にSwiftyなデータ処理とは何かを考察していきます。
第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
第2特集
「知りたい」「 使いたい」「 発信したい」をかなえる
OSSソースコードリーディングのススメ
特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画]Red Hat Enterprise Linux 9最新ガイド
短期連載
今さら聞けないSSH
[前編]リモートログインとコマンドの実行
短期連載
MySQLで学ぶ文字コード
[最終回]文字コードのハマりどころTips集
短期連載
新生「Ansible」徹底解説
[4]Playbookの実行環境(基礎編)