2

我目前正在开发一个瘦客户端应用程序,其中通信通过 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自省来确定参数。这个解决方案非常适合序列化(我重复一遍,这不是问题),但是在反序列化时,我会得到消息类型并丢失消息本身,至少如果我不解析它两次的话。通过 Java“模板”机制专门化 MessageWrapper 使我们回到最初的问题(我将有多个类可供选择)。

另一个想法是在 JSON 字符串之前发送一个标记来识别消息,例如:

Placement={"foo": 2, "bar": "baz"}

然后读取令牌以确定 .class 类型。这可以工作,但仍然存在一个问题:我将如何从我的receive函数返回值?我当然可以:

public Object receive(Reader stream) {}

并强迫用户做一个沮丧,但我宁愿避免它。

编辑:这是因为客户端具有类似反应器的结构:它在循环中运行并将消息分派给适当的处理程序。

4

2 回答 2

3

编辑:

好的,现在更清楚了。

拥有一个包含一系列已定义对象的 Wrapper 怎么样?你有几个处理程序?

我的意思是:

class HandlerWrapper {
    private final Placement placement;
    private final Update update;
}

然后客户端将反序列化并检查非空属性:

{"placement":{"foo": 2, "bar": "baz"}, "update":null, ...}

我知道这不是很好,但我想不出别的……:/


老的

我不认为这实际上是一个问题,因为您可以在规范中说明您必须从该特定情况中期望什么样的对象。

例如,如果您正在调用 API 来获取用户,那么您将期望 Object 中有一个 User.class。获取书籍(或其他)的 API 也是如此。

(我希望我理解这个问题)

于 2013-06-05T10:04:26.440 回答
3

使用 Gson,如果您有合理数量的可能消息,则可以创建一个包含所有消息的类(类似于@Enrichman所写的,但您不需要检查空值......)。例如,如果您有课程

public class Response {
    private Placement placement;
    private Update update;
    //more message types
    //getters & setters
}

然后你可以反序列化你的响应:

Gson gson = new Gson();
Response response = gson.fromJson(jsonString, Response.class);

它会反序列化这个 JSON:

{"placement": {...} }

和这个:

{"update": {...} }

和这个:

{"placement": {...}, "update": {...} }

Gson 将忽略 JSON 响应中与您的类中的任何属性不对应的所有字段,因此您可以使用单个类来反序列化多个响应...

于 2013-06-05T11:28:48.993 回答