swift-sion
前回予告どおり、
to type or not to type, that's the question.
前回記事より、
- Swift:swift-sion by dankogai
- Go:go-sion by mattn
- ECMAScript
(aka JavaScript):js-sion by dankogai - Rust:sion-rs by pandaman64
- Python 3:py-sion by kamimura
ここで言う
何のためにシリアライズするのか
たとえばSIONのDictionary。js-sionでは、String:SIONの場合はObject、Mapにデシリアライズされます。どちらもECMAScript 6には標準装備されている型です。それに対し、
一見、eval()でなされました。今ではJSON.という専用関数が組み込まれましたが、ArrayなりObjectなり、
しかし、Boolに相当する型が不在で、0ならfalse、trueという扱いです。これがPerlになると0 but trueなどという場合が出てきてさらにややこしい。こうした問題をどう解決するか。
必要は発明の母
「なければ作ればいい」。これは型にも当てはまります。Perlに標準装備のJSON::PPでは、JSON::PP::Booleanという型―Perlにおいてはクラス―を用意してこの問題を解決しています。ただし用意されているのはあくまでもJSONを表現するのに足りないデータ型だけで、JSON型というのは用意されていません。これはある意味当然で、
use JSON::PP;
my $array_ref = json_decode('[0,1]');
my $hash_ref = json_decode('{"one":1}')
の$array_は普通の配列リファレンス、$hash_は普通のハッシュJSON::PP::Booleanはある意味必要悪であり、"" . decode_は"1"となります。
シリアライズする2つの理由
それでは、SION型を用意したのでしょう。JSON同様、
理由は2つ。1つはSwiftにeval()が存在しないこと。同様のことは不可能ではありませんが、swiftcが必要になります。これはSwiftが根底で
もう1つは、ExpressiveBy*Literalプロトコル……、SION型が成立するのです。
import SION
御託はこれくらいにして、README.どおりに環境を整えたら、
import SION
とするだけです。これだけで、
var sion:SION = [
"nil": nil,
"bool": true,
"int": -42,
"double": 42.195,
"string": "漢字、カタカナ、ひらがなの入った
string",
"array": [nil, true, 1, 1.0, "one", [1],
["one":1.0]],
"dictionary": [
"nil":nil, "bool":false, "int":0, "double":0.0, "string":"","array":[], "object":[:]
],
"url":"https://github.com/dankogai/"
]
という具合にふつうにSIONをリテラルとして受け付けます。試しに:SIONを取ってみてください。どうなりましたか?
もちろん、
SION(string:sionStr)
SION(json:jsonStr)
SION(jsonUrlString:"https://api.github.com")
SION(propertyList:plistXML.data(using:.utf8)!, format:.xml)
SION(msgPack:msgData)
デシリアライゼーションはさらに簡単で、sion.でも"\(sion)"でもいいですし、print(sion)してもいいでしょう。
直感的なのは、
var sa = SION([])
で、
sa[0] = nil
sa[1] = true
sa[2] = 1
という具合にあたかも組込みの配列のように値を代入できますし、
var sd = SION([:])
sd["nil"] = nil
sd["bool"] = false
sd["int"] = 0
とできます。1点Arrayでは範囲外へのアクセスはfatalErrorになりますし、Dictionaryで存在しないキーはnilを返しますが、.Error()という特別な値を用意し、
もう1点注意を要するのは、
sa[1] = true // SION.Bool(true)
sa[2] = 1 // SION.Int(1)
であり、
sa[1].bool
sa[2].int
とします。なおこれらのコンピューテッド・
sion[2].int! += 1 // now 2
sion[3].double! *= 0.5 // now 0.5
sion[4].string!.removeLast() // now "on"
sion[5].array!.append(2) // now [1, 2]
sion[6].dictionary!["two"] = 2 // now
["one":1,"two":2]
次回予告
swift-sionやSwiftyJSONのような
本誌最新号をチェック!
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の実行環境(基礎編)
