使用未知的编译时类型对字段进行反序列化,其中字段指示类型 [英] Deserialising a generic with unknown compile time type where a field indicates the type

查看:90
本文介绍了使用未知的编译时类型对字段进行反序列化,其中字段指示类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个泛型类,在这个简单的例子中,它是如下所示:

  public class MsgWrapper< T> {
@Expose
private T消息;
@Expose
私人字符串类型;
private String uri;
}

串行化是令人讨厌的,但是微不足道的,例如

 类型t​​ypeToken = new TypeToken< MsgWrapper< Notice>>(){}。getType(); 
gson.toJson(message,typeToken);

服务器收到的json可以是

  MsgWrapper<公告>或MsgWrapper< Alert> 

如果是通知,那么'类型'字段会显示'notice'
If它是一个提示,然后'类型'字段将会显示'alert'。



目前我已经实现了一个自定义的反序列化程序

  public MsgWrapper deserialize(JsonElement json,Type typeOfT,JsonDeserializationContext context)throws JsonParseException {
JsonObject object = json.getAsJsonObject();
if(object.has(Type))
{
MsgWrapper msgWrapper = new MsgWrapper();
msgWrapper.setType(object.get(Type)。getAsString());
if(msgWrapper.getType()。equalsIgnoreCase(Notice))
{
msgWrapper.setMessage(context.deserialize(object.get(Message),Notice.class)) ;

else if(msgWrapper.getType()。equalsIgnoreCase(Alert))
{
msgWrapper.setMessage(context.deserialize(object.get(Message)) ,Alert.class));
}
return msgWrapper;
}
else
{
抛出新的JsonParseException(出错了......);
}
}
}

这感觉非常笨重和错误。有没有更好的方法?

解决方案

您发布的解决方案或多或少的多达多少与当前Gson版本的反序列化有关。

您可以实施一些小的更改,以使外部可自定义的解串器可配置,就像Dan提到的那样,使用 Map< String,Deserializer>



不用定制解串器,看起来Gson很快就会拥有 RuntimeTypeAdapter 可用于更简单的多态反序列化。请参阅 http://code.google.com/p/google- gson / issues / detail?id = 231 了解更多信息。即使您不能使用 RuntimeTypeAdapter ,它至少提供了一个创建可配置的自定义反序列化器的示例。



如果您可以切换JSON映射API,然后我建议考虑Jackson,因为它具有可用的相对简单的多态解串器机制。我在 http://programmerbruce.blogspot上发布了一些简单的示例.com / 2011/05 / deserialize-json-with-jackson-into.html


This works but it is horrible - is there a better way?

I have a generic class which in this simple example is as follows

public class MsgWrapper<T> {
@Expose
private T Message;
@Expose
private String Type;
private String uri;
}

Serialising is nasty but trivial e.g.

Type typeToken = new TypeToken<MsgWrapper<Notice>>(){}.getType();
gson.toJson(message,typeToken);

The server receives json which can be either

MsgWrapper<Notice> or MsgWrapper<Alert>

If it is a notice then the 'Type' field will say 'notice' If it is an alert then the 'Type' field will say 'alert'

At the moment I've implemented a custom deserialiser

        public MsgWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject object = json.getAsJsonObject();
        if(object.has("Type"))
        {
            MsgWrapper msgWrapper=new MsgWrapper();
            msgWrapper.setType(object.get("Type").getAsString());
            if(msgWrapper.getType().equalsIgnoreCase("Notice"))
            {
             msgWrapper.setMessage(context.deserialize(object.get("Message"), Notice.class));
            }
            else if(msgWrapper.getType().equalsIgnoreCase("Alert"))
            {
             msgWrapper.setMessage(context.deserialize(object.get("Message"), Alert.class));   
            }
            return msgWrapper;
        }
        else
        {
            throw new JsonParseException("something is wrong...");
        }
    }
}

This feels deeply clunky and wrong. Is there a better way?

解决方案

The solution you posted is more-or-less as good as it gets as far as polymorphic deserialization with the current Gson release is concerned.

You could implement some small changes to make the custom deserializer externally configurable, along the lines as Dan suggested with the mention of changing to use Map<String, Deserializer>.

Instead of using a custom deserializer, it looks like Gson will soon have the RuntimeTypeAdapter available for simpler polymorphic deserialization. See http://code.google.com/p/google-gson/issues/detail?id=231 for more info. Even if you cannot use the RuntimeTypeAdapter, it at least provides an example for creating a configurable custom deserializer.

If you can switch JSON mapping APIs, then I recommend considering Jackson, as it has a working and relatively simple polymorphic deserializer mechanism available. I posted some simple examples at http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

这篇关于使用未知的编译时类型对字段进行反序列化,其中字段指示类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆