Support EnumMap deserialization (#2071)
This commit is contained in:
parent
e2e851c9bc
commit
565b7a198e
@ -23,6 +23,7 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
@ -199,7 +200,26 @@ public final class ConstructorConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(rawType)) {
|
if (Map.class.isAssignableFrom(rawType)) {
|
||||||
if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
|
// Only support creation of EnumMap, but not of custom subtypes; for them type parameters
|
||||||
|
// and constructor parameter might have completely different meaning
|
||||||
|
if (rawType == EnumMap.class) {
|
||||||
|
return new ObjectConstructor<T>() {
|
||||||
|
@Override public T construct() {
|
||||||
|
if (type instanceof ParameterizedType) {
|
||||||
|
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
|
if (elementType instanceof Class) {
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
T map = (T) new EnumMap((Class) elementType);
|
||||||
|
return map;
|
||||||
|
} else {
|
||||||
|
throw new JsonIOException("Invalid EnumMap type: " + type.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new JsonIOException("Invalid EnumMap type: " + type.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
@Override public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new ConcurrentSkipListMap<Object, Object>();
|
return (T) new ConcurrentSkipListMap<Object, Object>();
|
||||||
|
@ -31,7 +31,10 @@ import com.google.gson.reflect.TypeToken;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
/**
|
/**
|
||||||
@ -150,6 +153,8 @@ public class EnumTest extends TestCase {
|
|||||||
public void testEnumSet() {
|
public void testEnumSet() {
|
||||||
EnumSet<Roshambo> foo = EnumSet.of(Roshambo.ROCK, Roshambo.PAPER);
|
EnumSet<Roshambo> foo = EnumSet.of(Roshambo.ROCK, Roshambo.PAPER);
|
||||||
String json = gson.toJson(foo);
|
String json = gson.toJson(foo);
|
||||||
|
assertEquals("[\"ROCK\",\"PAPER\"]", json);
|
||||||
|
|
||||||
Type type = new TypeToken<EnumSet<Roshambo>>() {}.getType();
|
Type type = new TypeToken<EnumSet<Roshambo>>() {}.getType();
|
||||||
EnumSet<Roshambo> bar = gson.fromJson(json, type);
|
EnumSet<Roshambo> bar = gson.fromJson(json, type);
|
||||||
assertTrue(bar.contains(Roshambo.ROCK));
|
assertTrue(bar.contains(Roshambo.ROCK));
|
||||||
@ -157,6 +162,18 @@ public class EnumTest extends TestCase {
|
|||||||
assertFalse(bar.contains(Roshambo.SCISSORS));
|
assertFalse(bar.contains(Roshambo.SCISSORS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEnumMap() throws Exception {
|
||||||
|
EnumMap<MyEnum, String> map = new EnumMap<MyEnum, String>(MyEnum.class);
|
||||||
|
map.put(MyEnum.VALUE1, "test");
|
||||||
|
String json = gson.toJson(map);
|
||||||
|
assertEquals("{\"VALUE1\":\"test\"}", json);
|
||||||
|
|
||||||
|
Type type = new TypeToken<EnumMap<MyEnum, String>>() {}.getType();
|
||||||
|
EnumMap<?, ?> actualMap = gson.fromJson("{\"VALUE1\":\"test\"}", type);
|
||||||
|
Map<?, ?> expectedMap = Collections.singletonMap(MyEnum.VALUE1, "test");
|
||||||
|
assertEquals(expectedMap, actualMap);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Roshambo {
|
public enum Roshambo {
|
||||||
ROCK {
|
ROCK {
|
||||||
@Override Roshambo defeats() {
|
@Override Roshambo defeats() {
|
||||||
|
Loading…
Reference in New Issue
Block a user