私は現在、JSON でシリアル化されたメッセージ オブジェクトを介して通信が行われるシン クライアント アプリケーションに取り組んでいます。サーバーはメッセージをシリアル化し、ソケットを介して送信し、クライアントは受信して逆シリアル化します。答えは同じように起こります。
まず、メッセージ クラスがサーバーとクライアントの両方で定義されていると仮定しましょう。
問題は、Gson::fromJson
関数がイントロスペクションを介してデシリアライズするために .class/type オブジェクトを必要とすることですが (当然)、私のアプリケーションでは、事前に .class を知らなくても複数のタイプのオブジェクトを受け取ることができます。
私のアイデアは、次のようなメッセージラッパーを作成することでした:
class MessageWrapper {
public class MessageWrapper(Object message, MessageType type) {
this.message = message;
this.type = type;
}
// getters...
public enum MesssageType {
PLACEMENT,
UPDATE,
// ...
}
private final Object message;
private final MessageType type;
}
type
または、イントロスペクションでパラメーターを決定することで、さらに進んでください。このソリューションはシリアライズには最適ですが (繰り返しますが、それは問題ではありません)、デシリアライズ中にメッセージの種類を取得し、少なくとも 2 回解析しないとメッセージ自体が失われます。Java の「テンプレート」メカニズムを使用して MessageWrapper を特殊化すると、元の問題に戻ります (複数のクラスから選択する必要があります)。
もう 1 つのアイデアは、次のように、JSON 文字列の前にメッセージを識別するトークンを送信することでした。
Placement={"foo": 2, "bar": "baz"}
次に、トークンを読み取って .class タイプを判別します。これは機能する可能性がありますが、まだ問題があります。関数から値を返すにはどうすればよいでしょうreceive
か? もちろん、私はできる:
public Object receive(Reader stream) {}
ユーザーにダウンキャストを強制しますが、私はそれを避けたいと思います。
編集: これは、クライアントがリアクターのような構造を持っているためです: ループで実行され、適切なハンドラーにメッセージをディスパッチします。