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()); } }
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.
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); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With