GSON Case-Insensitive Enum Deserialization

Steve picture Steve · Jan 30, 2012 · Viewed 14.1k times · Source

I have an enum:

enum Type {
    LIVE, UPCOMING, REPLAY
}

And some JSON:

{
    "type": "live"
}

And a class:

class Event {
    Type type;
}

When I try to deserialize the JSON, using GSON, I receive null for the Event type field, since the case of the type field in the JSON does not match that of the enum.

Events events = new Gson().fromJson(json, Event.class);

If I change the enum to the following, then all works fine:

enum Type {
    live, upcoming, replay
}

However, I would like to leave the enum constants as all uppercase.

I'm assuming I need to write an adapter but haven't found any good documentation or examples.

What is the best solution?


Edit:

I was able to get a JsonDeserializer working. Is there a more generic way to write this though, as it would be unfortunate to have to write this each time there is a case mismatch between enum values and JSON strings.

protected static class TypeCaseInsensitiveEnumAdapter implements JsonDeserializer<Type> {
    @Override
    public Type deserialize(JsonElement json, java.lang.reflect.Type classOfT, JsonDeserializationContext context)
            throws JsonParseException {         
        return Type.valueOf(json.getAsString().toUpperCase());
    }
}

Answer

prodaea picture prodaea · Aug 20, 2013

A simpler way I found (just now) to do this is to use the @SerializedName annotation. I found it in the EnumTest.java here (the Gender class around ln 195):

https://code.google.com/p/google-gson/source/browse/trunk/gson/src/test/java/com/google/gson/functional/EnumTest.java?r=1230

This assumes that all of your Types will come in as lowercase as opposed to being "case insensitive"

public enum Type {
    @SerializedName("live")
    LIVE,

    @SerializedName("upcoming")
    UPCOMING,

    @SerializedName("replay")
    REPLAY;
}

This was the simplest and most generic way I found to do this. Hope it helps you.