Merge pull request #730 from google/624
Added support to serialize/deserialize ConcurrentMap and ConcurrentNa…
This commit is contained in:
commit
64107353a3
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
package com.google.gson.internal;
|
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.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
@ -37,6 +33,14 @@ import java.util.SortedMap;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.TreeSet;
|
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.
|
* 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);
|
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
|
||||||
if (typeCreator != null) {
|
if (typeCreator != null) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return typeCreator.createInstance(type);
|
return typeCreator.createInstance(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -70,7 +74,7 @@ public final class ConstructorConstructor {
|
||||||
(InstanceCreator<T>) instanceCreators.get(rawType);
|
(InstanceCreator<T>) instanceCreators.get(rawType);
|
||||||
if (rawTypeCreator != null) {
|
if (rawTypeCreator != null) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return rawTypeCreator.createInstance(type);
|
return rawTypeCreator.createInstance(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -98,7 +102,7 @@ public final class ConstructorConstructor {
|
||||||
}
|
}
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
@SuppressWarnings("unchecked") // T is the same raw type as is requested
|
@SuppressWarnings("unchecked") // T is the same raw type as is requested
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
try {
|
try {
|
||||||
Object[] args = null;
|
Object[] args = null;
|
||||||
return (T) constructor.newInstance(args);
|
return (T) constructor.newInstance(args);
|
||||||
|
@ -130,14 +134,14 @@ public final class ConstructorConstructor {
|
||||||
if (Collection.class.isAssignableFrom(rawType)) {
|
if (Collection.class.isAssignableFrom(rawType)) {
|
||||||
if (SortedSet.class.isAssignableFrom(rawType)) {
|
if (SortedSet.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new TreeSet<Object>();
|
return (T) new TreeSet<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (EnumSet.class.isAssignableFrom(rawType)) {
|
} else if (EnumSet.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
if (elementType instanceof Class) {
|
if (elementType instanceof Class) {
|
||||||
|
@ -152,19 +156,19 @@ public final class ConstructorConstructor {
|
||||||
};
|
};
|
||||||
} else if (Set.class.isAssignableFrom(rawType)) {
|
} else if (Set.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new LinkedHashSet<Object>();
|
return (T) new LinkedHashSet<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (Queue.class.isAssignableFrom(rawType)) {
|
} else if (Queue.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new LinkedList<Object>();
|
return (T) new LinkedList<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new ArrayList<Object>();
|
return (T) new ArrayList<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -172,22 +176,34 @@ public final class ConstructorConstructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(rawType)) {
|
if (Map.class.isAssignableFrom(rawType)) {
|
||||||
if (SortedMap.class.isAssignableFrom(rawType)) {
|
if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
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>();
|
return (T) new TreeMap<Object, Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
|
} else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
|
||||||
TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
|
TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new LinkedHashMap<Object, Object>();
|
return (T) new LinkedHashMap<Object, Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
return (T) new LinkedTreeMap<String, Object>();
|
return (T) new LinkedTreeMap<String, Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -202,7 +218,7 @@ public final class ConstructorConstructor {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T construct() {
|
@Override public T construct() {
|
||||||
try {
|
try {
|
||||||
Object newInstance = unsafeAllocator.newInstance(rawType);
|
Object newInstance = unsafeAllocator.newInstance(rawType);
|
||||||
return (T) newInstance;
|
return (T) newInstance;
|
||||||
|
|
|
@ -16,6 +16,18 @@
|
||||||
|
|
||||||
package com.google.gson.functional;
|
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.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.InstanceCreator;
|
import com.google.gson.InstanceCreator;
|
||||||
|
@ -33,14 +45,6 @@ import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
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
|
* Functional test for Json serialization and deserialization for Maps
|
||||||
*
|
*
|
||||||
|
@ -179,6 +183,46 @@ public class MapTest extends TestCase {
|
||||||
assertEquals("456", map.get(123));
|
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() {
|
public void testParameterizedMapSubclassSerialization() {
|
||||||
MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>(10);
|
MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>(10);
|
||||||
map.put("a", "b");
|
map.put("a", "b");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user