GSON Case-Insensitive Enum Deserialization

Now you can add multiple values for @SerializedName like this:

public enum Type {
    @SerializedName(value = "live", alternate = {"LIVE"})
    LIVE,

    @SerializedName(value = "upcoming", alternate = {"UPCOMING"})
    UPCOMING,

    @SerializedName(value = "replay", alternate = {"REPLAY"})
    REPLAY;
}

I think it's a bit late for you but I hope it will help anyone else!


Conveniently for you, this is very close to the example given in TypeAdapterFactory's Javadoc:

public class CaseInsensitiveEnumTypeAdapterFactory implements TypeAdapterFactory {
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<T> rawType = (Class<T>) type.getRawType();
    if (!rawType.isEnum()) {
      return null;
    }
 
    final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
    for (T constant : rawType.getEnumConstants()) {
      lowercaseToConstant.put(toLowercase(constant), constant);
    }
 
    return new TypeAdapter<T>() {
      public void write(JsonWriter out, T value) throws IOException {
        if (value == null) {
          out.nullValue();
        } else {
          out.value(toLowercase(value));
        }
      }
 
      public T read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        } else {
          return lowercaseToConstant.get(toLowercase(reader.nextString()));
        }
      }
    };
  }

  private String toLowercase(Object o) {
    return o.toString().toLowerCase(Locale.US);
  }
}

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.