2つの異なるDartアプリケーションで型安全にデータを送受信する方法
とりあえずサーバーとクライアントでWebSocketでデータをやりとりするとします。
普通のSocketやHTTPでも変わりません。
お題↓
本のIDを送信したらその本のことを教えてもらえる
まず標準APIだけで書くとこう
//client
ws.send(JSON.encode({"id":1}));
//server
void onMessage(String str){
Map<String,int> data = JSON.decode(str);
ws.write(JSON.encode(getBookData(data["id"])));
}
やはりオブジェクトをJSONで表そうと思ったらまずMapで表現することを思いつきますが
この方法には明らかな欠点があります。
Keyをミスなく共有しなければいけないことです。
そして型もわかりません。
data["id"]とdata["name"]の型が違うことはDartEditorにはわかりません。
一本のWebSocketを使いまわすことの問題点
当然一本のWebSocketをいろんなリクエストに使いまわすわけですから頭にリクエストの宛先を書かなければいけません。
HTTPでいうところのURLです。
//client
ws.send(JSON.encode(["book",{"id":1}}]));
ws.send(JSON.encode(["author",{"name":"ロバート・A・ハインライン"}]));
//server
void onMessage(String str){
List data = JSON.decode(str);
switch(data[0]){
case "book" :
getBook(data[1]);
break;
case "author" :
getAuthor(data[1]);
break;
}
}
これは数が増えれば増えるほど大変なことになります。 もちろんどこかに定数を定義してといったこともしますが本質的な解決にはなりません。
そこで
サーバーもクライアントもDartで作るなら共通の何かを記述することでプログラミング的に解決できないか。
ということでこういうの作りました。
仕組みをざっくりと説明しますと、まずあなたがデータの構造を定義します。データの構造とはパラメータの名前と型のことです。
するとこの構造体に自動で一意のIDがふられます。
サーバーとクライアントで同じファイルを実行するはずなので、このIDと構造の組み合わせは必ず両者で一緒になるはずです。
そしてこの構造体に値を登録しsend()すると構造体のIDとパラメータが自動で転送されます。
すると反対側ではIDを元にどの構造宛のデータか判断しその構造体のパラメータに値を設定しStreamイベントを起こします。
詳しい使い方はexampleのbooks.dartをご覧ください。