Skip to content

Commit 6410735

Browse files
committed
Merge pull request google#730 from google/624
Added support to serialize/deserialize ConcurrentMap and ConcurrentNa…
2 parents 9e5f86d + fef43b2 commit 6410735

File tree

2 files changed

+85
-25
lines changed

2 files changed

+85
-25
lines changed

gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616

1717
package com.google.gson.internal;
1818

19-
import com.google.gson.InstanceCreator;
20-
import com.google.gson.JsonIOException;
21-
import com.google.gson.reflect.TypeToken;
22-
2319
import java.lang.reflect.Constructor;
2420
import java.lang.reflect.InvocationTargetException;
2521
import java.lang.reflect.ParameterizedType;
@@ -37,6 +33,14 @@
3733
import java.util.SortedSet;
3834
import java.util.TreeMap;
3935
import java.util.TreeSet;
36+
import java.util.concurrent.ConcurrentHashMap;
37+
import java.util.concurrent.ConcurrentMap;
38+
import java.util.concurrent.ConcurrentNavigableMap;
39+
import java.util.concurrent.ConcurrentSkipListMap;
40+
41+
import com.google.gson.InstanceCreator;
42+
import com.google.gson.JsonIOException;
43+
import com.google.gson.reflect.TypeToken;
4044

4145
/**
4246
* Returns a function that can construct an instance of a requested type.
@@ -58,7 +62,7 @@ public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
5862
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
5963
if (typeCreator != null) {
6064
return new ObjectConstructor<T>() {
61-
public T construct() {
65+
@Override public T construct() {
6266
return typeCreator.createInstance(type);
6367
}
6468
};
@@ -70,7 +74,7 @@ public T construct() {
7074
(InstanceCreator<T>) instanceCreators.get(rawType);
7175
if (rawTypeCreator != null) {
7276
return new ObjectConstructor<T>() {
73-
public T construct() {
77+
@Override public T construct() {
7478
return rawTypeCreator.createInstance(type);
7579
}
7680
};
@@ -98,7 +102,7 @@ private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType)
98102
}
99103
return new ObjectConstructor<T>() {
100104
@SuppressWarnings("unchecked") // T is the same raw type as is requested
101-
public T construct() {
105+
@Override public T construct() {
102106
try {
103107
Object[] args = null;
104108
return (T) constructor.newInstance(args);
@@ -130,14 +134,14 @@ private <T> ObjectConstructor<T> newDefaultImplementationConstructor(
130134
if (Collection.class.isAssignableFrom(rawType)) {
131135
if (SortedSet.class.isAssignableFrom(rawType)) {
132136
return new ObjectConstructor<T>() {
133-
public T construct() {
137+
@Override public T construct() {
134138
return (T) new TreeSet<Object>();
135139
}
136140
};
137141
} else if (EnumSet.class.isAssignableFrom(rawType)) {
138142
return new ObjectConstructor<T>() {
139143
@SuppressWarnings("rawtypes")
140-
public T construct() {
144+
@Override public T construct() {
141145
if (type instanceof ParameterizedType) {
142146
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
143147
if (elementType instanceof Class) {
@@ -152,42 +156,54 @@ public T construct() {
152156
};
153157
} else if (Set.class.isAssignableFrom(rawType)) {
154158
return new ObjectConstructor<T>() {
155-
public T construct() {
159+
@Override public T construct() {
156160
return (T) new LinkedHashSet<Object>();
157161
}
158162
};
159163
} else if (Queue.class.isAssignableFrom(rawType)) {
160164
return new ObjectConstructor<T>() {
161-
public T construct() {
165+
@Override public T construct() {
162166
return (T) new LinkedList<Object>();
163167
}
164168
};
165169
} else {
166170
return new ObjectConstructor<T>() {
167-
public T construct() {
171+
@Override public T construct() {
168172
return (T) new ArrayList<Object>();
169173
}
170174
};
171175
}
172176
}
173177

174178
if (Map.class.isAssignableFrom(rawType)) {
175-
if (SortedMap.class.isAssignableFrom(rawType)) {
179+
if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
180+
return new ObjectConstructor<T>() {
181+
@Override public T construct() {
182+
return (T) new ConcurrentSkipListMap<Object, Object>();
183+
}
184+
};
185+
} else if (ConcurrentMap.class.isAssignableFrom(rawType)) {
186+
return new ObjectConstructor<T>() {
187+
@Override public T construct() {
188+
return (T) new ConcurrentHashMap<Object, Object>();
189+
}
190+
};
191+
} else if (SortedMap.class.isAssignableFrom(rawType)) {
176192
return new ObjectConstructor<T>() {
177-
public T construct() {
193+
@Override public T construct() {
178194
return (T) new TreeMap<Object, Object>();
179195
}
180196
};
181197
} else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
182198
TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
183199
return new ObjectConstructor<T>() {
184-
public T construct() {
200+
@Override public T construct() {
185201
return (T) new LinkedHashMap<Object, Object>();
186202
}
187203
};
188204
} else {
189205
return new ObjectConstructor<T>() {
190-
public T construct() {
206+
@Override public T construct() {
191207
return (T) new LinkedTreeMap<String, Object>();
192208
}
193209
};
@@ -202,7 +218,7 @@ private <T> ObjectConstructor<T> newUnsafeAllocator(
202218
return new ObjectConstructor<T>() {
203219
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
204220
@SuppressWarnings("unchecked")
205-
public T construct() {
221+
@Override public T construct() {
206222
try {
207223
Object newInstance = unsafeAllocator.newInstance(rawType);
208224
return (T) newInstance;

gson/src/test/java/com/google/gson/functional/MapTest.java

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616

1717
package com.google.gson.functional;
1818

19+
import java.lang.reflect.Type;
20+
import java.util.Collection;
21+
import java.util.HashMap;
22+
import java.util.LinkedHashMap;
23+
import java.util.Map;
24+
import java.util.SortedMap;
25+
import java.util.TreeMap;
26+
import java.util.concurrent.ConcurrentHashMap;
27+
import java.util.concurrent.ConcurrentMap;
28+
import java.util.concurrent.ConcurrentNavigableMap;
29+
import java.util.concurrent.ConcurrentSkipListMap;
30+
1931
import com.google.gson.Gson;
2032
import com.google.gson.GsonBuilder;
2133
import com.google.gson.InstanceCreator;
@@ -33,14 +45,6 @@
3345

3446
import junit.framework.TestCase;
3547

36-
import java.lang.reflect.Type;
37-
import java.util.Collection;
38-
import java.util.HashMap;
39-
import java.util.LinkedHashMap;
40-
import java.util.Map;
41-
import java.util.SortedMap;
42-
import java.util.TreeMap;
43-
4448
/**
4549
* Functional test for Json serialization and deserialization for Maps
4650
*
@@ -179,6 +183,46 @@ public void testSortedMap() throws Exception {
179183
assertEquals("456", map.get(123));
180184
}
181185

186+
public void testConcurrentMap() throws Exception {
187+
Type typeOfMap = new TypeToken<ConcurrentMap<Integer, String>>() {}.getType();
188+
ConcurrentMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
189+
assertEquals(1, map.size());
190+
assertTrue(map.containsKey(123));
191+
assertEquals("456", map.get(123));
192+
String json = gson.toJson(map);
193+
assertEquals("{\"123\":\"456\"}", json);
194+
}
195+
196+
public void testConcurrentHashMap() throws Exception {
197+
Type typeOfMap = new TypeToken<ConcurrentHashMap<Integer, String>>() {}.getType();
198+
ConcurrentHashMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
199+
assertEquals(1, map.size());
200+
assertTrue(map.containsKey(123));
201+
assertEquals("456", map.get(123));
202+
String json = gson.toJson(map);
203+
assertEquals("{\"123\":\"456\"}", json);
204+
}
205+
206+
public void testConcurrentNavigableMap() throws Exception {
207+
Type typeOfMap = new TypeToken<ConcurrentNavigableMap<Integer, String>>() {}.getType();
208+
ConcurrentNavigableMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
209+
assertEquals(1, map.size());
210+
assertTrue(map.containsKey(123));
211+
assertEquals("456", map.get(123));
212+
String json = gson.toJson(map);
213+
assertEquals("{\"123\":\"456\"}", json);
214+
}
215+
216+
public void testConcurrentSkipListMap() throws Exception {
217+
Type typeOfMap = new TypeToken<ConcurrentSkipListMap<Integer, String>>() {}.getType();
218+
ConcurrentSkipListMap<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap);
219+
assertEquals(1, map.size());
220+
assertTrue(map.containsKey(123));
221+
assertEquals("456", map.get(123));
222+
String json = gson.toJson(map);
223+
assertEquals("{\"123\":\"456\"}", json);
224+
}
225+
182226
public void testParameterizedMapSubclassSerialization() {
183227
MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>(10);
184228
map.put("a", "b");

0 commit comments

Comments
 (0)