我正试图在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自动序列化非Object字段,但对该messageData字段使用自定义序列化程序,同时考虑messageType?
可能有点晚了,但这个关于RuntimeTypeAdapter的答案可能会帮助您解决这个问题:
https://stackoverflow.com/a/15737704/433421
RuntimeTypeAdapter使您能够评估JSON中的自配置类型属性,在您的情况下为"messageType",并使用提供的POJO类注册其值。
查看此答案中提供的链接,可以查看javadoc中的用法示例。
据我所知,GSon将处理这些POJO类本身的序列化和反序列化
如果messageData中的这些字段包含任意对象,则必须像使用MessageJsonDeserializer一样注册自定义JsonDeselializer实例。
希望这能有所帮助。
遗憾的是,没有。至少我无法确定。没有办法让它做类似于"自定义反序列化字段X,但对它的其余部分执行super.destrialize()"的操作。天知道我试过了。如果有什么安慰的话,我看过的每一个Json反序列化程序似乎都是这样。