Merge pull request #730 from google/624

Added support to serialize/deserialize ConcurrentMap and ConcurrentNa…
This commit is contained in:
Jesse Wilson 2015-11-05 07:25:34 -05:00
commit 64107353a3
2 changed files with 85 additions and 25 deletions

View File

@ -16,10 +16,6 @@
package com.google.gson.internal;
import com.google.gson.InstanceCreator;
import com.google.gson.JsonIOException;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
@ -37,6 +33,14 @@ import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import com.google.gson.InstanceCreator;
import com.google.gson.JsonIOException;
import com.google.gson.reflect.TypeToken;
/**
* Returns a function that can construct an instance of a requested type.
@ -58,7 +62,7 @@ public final class ConstructorConstructor {
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return typeCreator.createInstance(type);
}
};
@ -70,7 +74,7 @@ public final class ConstructorConstructor {
(InstanceCreator<T>) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
}
};
@ -98,7 +102,7 @@ public final class ConstructorConstructor {
}
return new ObjectConstructor<T>() {
@SuppressWarnings("unchecked") // T is the same raw type as is requested
public T construct() {
@Override public T construct() {
try {
Object[] args = null;
return (T) constructor.newInstance(args);
@ -130,14 +134,14 @@ public final class ConstructorConstructor {
if (Collection.class.isAssignableFrom(rawType)) {
if (SortedSet.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new TreeSet<Object>();
}
};
} else if (EnumSet.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@SuppressWarnings("rawtypes")
public T construct() {
@Override public T construct() {
if (type instanceof ParameterizedType) {
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
if (elementType instanceof Class) {
@ -152,19 +156,19 @@ public final class ConstructorConstructor {
};
} else if (Set.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new LinkedHashSet<Object>();
}
};
} else if (Queue.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new LinkedList<Object>();
}
};
} else {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new ArrayList<Object>();
}
};
@ -172,22 +176,34 @@ public final class ConstructorConstructor {
}
if (Map.class.isAssignableFrom(rawType)) {
if (SortedMap.class.isAssignableFrom(rawType)) {
if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new ConcurrentSkipListMap<Object, Object>();
}
};
} else if (ConcurrentMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new ConcurrentHashMap<Object, Object>();
}
};
} else if (SortedMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new TreeMap<Object, Object>();
}
};
} else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new LinkedHashMap<Object, Object>();
}
};
} else {
return new ObjectConstructor<T>() {
public T construct() {
@Override public T construct() {
return (T) new LinkedTreeMap<String, Object>();
}
};
@ -202,7 +218,7 @@ public final class ConstructorConstructor {
return new ObjectConstructor<T>() {
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
@SuppressWarnings("unchecked")
public T construct() {
@Override public T construct() {
try {
Object newInstance = unsafeAllocator.newInstance(rawType);
return (T) newInstance;

View File

@ -16,6 +16,18 @@
package com.google.gson.functional;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
@ -33,14 +45,6 @@ import com.google.gson.reflect.TypeToken;
import junit.framework.TestCase;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Functional test for Json serialization and deserialization for Maps
*
@ -179,6 +183,46 @@ public class MapTest extends TestCase {
assertEquals("456", map.get(123));
}
public void testConcurrentMap() throws Exception {
Type typeOfMap = new TypeToken<ConcurrentMap<Integer, String>>() {}.getType();
ConcurrentMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
assertEquals(1, map.size());
assertTrue(map.containsKey(123));
assertEquals("456", map.get(123));
String json = gson.toJson(map);
assertEquals("{\"123\":\"456\"}", json);
}
public void testConcurrentHashMap() throws Exception {
Type typeOfMap = new TypeToken<ConcurrentHashMap<Integer, String>>() {}.getType();
ConcurrentHashMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
assertEquals(1, map.size());
assertTrue(map.containsKey(123));
assertEquals("456", map.get(123));
String json = gson.toJson(map);
assertEquals("{\"123\":\"456\"}", json);
}
public void testConcurrentNavigableMap() throws Exception {
Type typeOfMap = new TypeToken<ConcurrentNavigableMap<Integer, String>>() {}.getType();
ConcurrentNavigableMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
assertEquals(1, map.size());
assertTrue(map.containsKey(123));
assertEquals("456", map.get(123));
String json = gson.toJson(map);
assertEquals("{\"123\":\"456\"}", json);
}
public void testConcurrentSkipListMap() throws Exception {
Type typeOfMap = new TypeToken<ConcurrentSkipListMap<Integer, String>>() {}.getType();
ConcurrentSkipListMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
assertEquals(1, map.size());
assertTrue(map.containsKey(123));
assertEquals("456", map.get(123));
String json = gson.toJson(map);
assertEquals("{\"123\":\"456\"}", json);
}
public void testParameterizedMapSubclassSerialization() {
MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>(10);
map.put("a", "b");