書いて覚えるSwift入門

第40回新しいフォーマット「SION」紹介

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ならStorableRubyならMarshalPythonなら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]
  • DateDataがサポートされていない

MessagePackはバイナリフォーマットに特化することでJSONの不満をかなり解消しました。数値型はずっとコンパクトで、辞書のキーにはMessagePack自体でシリアライズできるデータはなんでも使える。しかしバイナリフォーマットだけあって人が直接読み書きするのは無理ゲー……。

――というわけで筆者は「テキスト版のMessagePack」を探していたのですが、ある日気づいてしまったのです。⁠それってSwiftのリテラルでよくね?」と。

そうしてSIONが爆誕しました。

ご覧のとおり表1リスト4⁠、

  • 辞書は{}ではなく[]で括る。空の辞書は[:]とすることで配列[]と区別しているのはSwiftと同様
  • コメント可能。//から改行までがコメント
  • DataDateも扱える
  • 数値はIntDoubleを別のものとして扱う
    • DoubleNaN±Infinityも受け付ける
    • → 16進表記も受け付ける。これにより精度劣化が防げる
  • SIONで扱える型ならすべて辞書のキーとして使える
表1 SIONと他言語の比較
TypeSIONMsgPackJSONProperty
List
Comment
Nilplist: .binary only
Bool
Int64bit
DoubleJSON's Number
Stringutf-8 encoded
Databinary 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なデータ処理とは何かを考察していきます。

Software Design

本誌最新号をチェック!
Software Design 2022年9月号

2022年8月18日発売
B5判/192ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    MySQL アプリ開発者の必修5科目
    不意なトラブルに困らないためのRDB基礎知識
  • 第2特集
    「知りたい」⁠使いたい」⁠発信したい」をかなえる
    OSSソースコードリーディングのススメ
  • 特別企画
    企業のシステムを支えるOSとエコシステムの全貌
    [特別企画]Red Hat Enterprise Linux 9最新ガイド
  • 短期連載
    今さら聞けないSSH
    [前編]リモートログインとコマンドの実行
  • 短期連載
    MySQLで学ぶ文字コード
    [最終回]文字コードのハマりどころTips集
  • 短期連載
    新生「Ansible」徹底解説
    [4]Playbookの実行環境(基礎編)

おすすめ記事

記事・ニュース一覧