mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 16:09:21 +08:00
Merge pull request #119 from serj-lotutovici/sl/json_for_enums
Enable Json annotation for enum values.
This commit is contained in:
@@ -21,6 +21,7 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -52,7 +53,7 @@ final class StandardJsonAdapters {
|
|||||||
Class<?> rawType = Types.getRawType(type);
|
Class<?> rawType = Types.getRawType(type);
|
||||||
if (rawType.isEnum()) {
|
if (rawType.isEnum()) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return enumAdapter((Class<? extends Enum>) rawType).nullSafe();
|
return new EnumJsonAdapter<>((Class<? extends Enum>) rawType).nullSafe();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -212,27 +213,46 @@ final class StandardJsonAdapters {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static <T extends Enum<T>> JsonAdapter<T> enumAdapter(final Class<T> enumType) {
|
static final class EnumJsonAdapter<T extends Enum<T>> extends JsonAdapter<T> {
|
||||||
return new JsonAdapter<T>() {
|
private final Class<T> enumType;
|
||||||
|
private final Map<String, T> nameConstantMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
public EnumJsonAdapter(Class<T> 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 {
|
@Override public T fromJson(JsonReader reader) throws IOException {
|
||||||
String name = reader.nextString();
|
String name = reader.nextString();
|
||||||
try {
|
T constant = nameConstantMap.get(name);
|
||||||
return Enum.valueOf(enumType, name);
|
if (constant != null) return constant;
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new JsonDataException("Expected one of "
|
throw new JsonDataException("Expected one of "
|
||||||
+ Arrays.toString(enumType.getEnumConstants()) + " but was " + name + " at path "
|
+ nameConstantMap.keySet() + " but was " + name + " at path "
|
||||||
+ reader.getPath());
|
+ reader.getPath());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void toJson(JsonWriter writer, T value) throws IOException {
|
@Override public void toJson(JsonWriter writer, T value) throws IOException {
|
||||||
writer.value(value.name());
|
for (Map.Entry<String, T> entry : nameConstantMap.entrySet()) {
|
||||||
|
if (entry.getValue() == value) {
|
||||||
|
writer.value(entry.getKey());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
return "JsonAdapter(" + enumType.getName() + ")";
|
return "JsonAdapter(" + enumType.getName() + ")";
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -672,6 +672,13 @@ public final class MoshiTest {
|
|||||||
assertThat(adapter.toJson(Roshambo.PAPER)).isEqualTo("\"PAPER\"");
|
assertThat(adapter.toJson(Roshambo.PAPER)).isEqualTo("\"PAPER\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void annotatedEnum() throws Exception {
|
||||||
|
Moshi moshi = new Moshi.Builder().build();
|
||||||
|
JsonAdapter<Roshambo> 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 {
|
@Test public void invalidEnum() throws Exception {
|
||||||
Moshi moshi = new Moshi.Builder().build();
|
Moshi moshi = new Moshi.Builder().build();
|
||||||
JsonAdapter<Roshambo> adapter = moshi.adapter(Roshambo.class).lenient();
|
JsonAdapter<Roshambo> adapter = moshi.adapter(Roshambo.class).lenient();
|
||||||
@@ -680,7 +687,7 @@ public final class MoshiTest {
|
|||||||
fail();
|
fail();
|
||||||
} catch (JsonDataException expected) {
|
} catch (JsonDataException expected) {
|
||||||
assertThat(expected).hasMessage(
|
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 {
|
enum Roshambo {
|
||||||
ROCK,
|
ROCK,
|
||||||
PAPER,
|
PAPER,
|
||||||
SCISSORS
|
@Json(name = "scr") SCISSORS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
|
Reference in New Issue
Block a user