0

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?

Ben
  • 1
  • 1
  • I would have used a factory, or at least a Map in lieu of the ifs. Other than that... looks OK to me – Dan Mar 27 '11 at 19:03

1 Answers1

1

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.

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97