2

我正在尝试在 Gson 中为一个对象创建一个自定义反序列化器,该对象实际上只是一堆具有类型标识符的不同类型的包装器。

这是我的问题域的简化概述:

我让用户互相发送消息,其中可能包含各种不相关的域对象,我想将其反序列化为:

public class Message {
    public String messageType;
    public Object messageData;
}

messageData 对象是通过 JavaScript 构造的,程序员决定将每种对象类型塞入一个字段“messageData”。messageData 可以是任意数量的域对象,例如:用户、视频、网站、图片,它们不共享基类或接口。

因此(简化的)json 对象可能如下所示:

{ "messageType": "video", "messageData": { "videoId": 1, "videoTitle": "my vid" } }

或者

{ "messageType": "picture", "messageData": { "pictureId": 1, "pictureUrl": "http://www.example.com/cat.jpg" } }

目标是获取 messageType 并使用它来选择一个适当的类来反序列化它。

我想出了这样的事情:

public class MessageJsonDeserializer implements JsonDeserializer<Message> {

    @Override
    public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {


        JsonObject obj = json.getAsJsonObject();
        Message message = new Message();
        message.messageType = obj.get("messageType").getAsString();
        message.messageData = MessageDataMapper.map(message.messageType, obj.get("messageData")); // maps and casts to the correct Video/Picture,Website etc..
        return message;
    }
}

这似乎工作正常,但假设 Message 有很多其他可以自动序列化的字段,那么我必须手动解析 JsonObject 并提取这些字段。

有没有一种方法可以让我使用混合方法并让 Gson 自动序列化非对象字段,但为该 messageData 字段使用自定义序列化程序,该字段还考虑到 messageType?

4

2 回答 2

2

可能有点晚了,但这个关于 RuntimeTypeAdapter 的答案可能会帮助您解决这个问题:

https://stackoverflow.com/a/15737704/433421

RuntimeTypeAdapter 使您能够评估 JSON 中的自配置类型属性,在您的情况下为“messageType”,并使用提供的 POJO 类注册其值。

查看此答案中提供的链接以查看 javadoc 中的用法示例。

据我了解,GSon 将处理这些 POJO 类本身的序列化和反序列化。

如果 messageData 中的这些字段包含任意对象,则您必须像使用 MessageJsonDeserializer 一样注册自定义 JsonDeserializer 实例。

希望这可以帮助。

于 2014-01-13T14:23:03.743 回答
1

可悲的是没有。至少我无法确定。没有办法让它执行类似“自定义反序列化字段 X,但其余部分为 super.deserialize()”之类的操作。天知道我试过了。如果有什么安慰的话,我看过的每个 Json 反序列化器似乎都是如此。

于 2013-08-26T21:16:51.703 回答