diff --git a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java index 0d7feba..3ad71cb 100644 --- a/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java +++ b/moshi/src/main/java/com/squareup/moshi/StandardJsonAdapters.java @@ -21,6 +21,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -52,7 +53,7 @@ final class StandardJsonAdapters { Class rawType = Types.getRawType(type); if (rawType.isEnum()) { //noinspection unchecked - return enumAdapter((Class) rawType).nullSafe(); + return new EnumJsonAdapter<>((Class) rawType).nullSafe(); } return null; } @@ -212,27 +213,46 @@ final class StandardJsonAdapters { } }; - static > JsonAdapter enumAdapter(final Class enumType) { - return new JsonAdapter() { - @Override public T fromJson(JsonReader reader) throws IOException { - String name = reader.nextString(); - try { - return Enum.valueOf(enumType, name); - } catch (IllegalArgumentException e) { - throw new JsonDataException("Expected one of " - + Arrays.toString(enumType.getEnumConstants()) + " but was " + name + " at path " - + reader.getPath()); + static final class EnumJsonAdapter> extends JsonAdapter { + private final Class enumType; + private final Map nameConstantMap = new LinkedHashMap<>(); + + public EnumJsonAdapter(Class enumType) { + this.enumType = enumType; + try { + T[] constants = enumType.getEnumConstants(); + for (T constant : constants) { + Json annotation = enumType.getField(constant.name()).getAnnotation(Json.class); + String name = annotation != null ? annotation.name() : constant.name(); + nameConstantMap.put(name, constant); + } + } catch (NoSuchFieldException e) { + throw new AssertionError("Missing field in " + enumType.getName(), e); + } + + } + + @Override public T fromJson(JsonReader reader) throws IOException { + String name = reader.nextString(); + T constant = nameConstantMap.get(name); + if (constant != null) return constant; + throw new JsonDataException("Expected one of " + + nameConstantMap.keySet() + " but was " + name + " at path " + + reader.getPath()); + } + + @Override public void toJson(JsonWriter writer, T value) throws IOException { + for (Map.Entry entry : nameConstantMap.entrySet()) { + if (entry.getValue() == value) { + writer.value(entry.getKey()); + break; } } + } - @Override public void toJson(JsonWriter writer, T value) throws IOException { - writer.value(value.name()); - } - - @Override public String toString() { - return "JsonAdapter(" + enumType.getName() + ")"; - } - }; + @Override public String toString() { + return "JsonAdapter(" + enumType.getName() + ")"; + } } /** diff --git a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java index 92d21d5..0acff82 100644 --- a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java +++ b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java @@ -672,6 +672,13 @@ public final class MoshiTest { assertThat(adapter.toJson(Roshambo.PAPER)).isEqualTo("\"PAPER\""); } + @Test public void annotatedEnum() throws Exception { + Moshi moshi = new Moshi.Builder().build(); + JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); + assertThat(adapter.fromJson("\"scr\"")).isEqualTo(Roshambo.SCISSORS); + assertThat(adapter.toJson(Roshambo.SCISSORS)).isEqualTo("\"scr\""); + } + @Test public void invalidEnum() throws Exception { Moshi moshi = new Moshi.Builder().build(); JsonAdapter adapter = moshi.adapter(Roshambo.class).lenient(); @@ -680,7 +687,7 @@ public final class MoshiTest { fail(); } catch (JsonDataException expected) { assertThat(expected).hasMessage( - "Expected one of [ROCK, PAPER, SCISSORS] but was SPOCK at path $"); + "Expected one of [ROCK, PAPER, scr] but was SPOCK at path $"); } } @@ -930,7 +937,7 @@ public final class MoshiTest { enum Roshambo { ROCK, PAPER, - SCISSORS + @Json(name = "scr") SCISSORS } @Retention(RUNTIME)