| /* |
| * Copyright (C) 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.gson.functional; |
| |
| import com.google.gson.Gson; |
| import com.google.gson.GsonBuilder; |
| import com.google.gson.InstanceCreator; |
| import com.google.gson.JsonArray; |
| import com.google.gson.JsonElement; |
| import com.google.gson.JsonPrimitive; |
| import com.google.gson.JsonSerializationContext; |
| import com.google.gson.JsonSerializer; |
| import com.google.gson.common.TestTypes; |
| import com.google.gson.internal.$Gson$Types; |
| 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.TreeMap; |
| |
| /** |
| * Functional test for Json serialization and deserialization for Maps |
| * |
| * @author Inderjeet Singh |
| * @author Joel Leitch |
| */ |
| public class MapTest extends TestCase { |
| private Gson gson; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| gson = new Gson(); |
| } |
| |
| public void testMapSerialization() { |
| Map<String, Integer> map = new LinkedHashMap<String, Integer>(); |
| map.put("a", 1); |
| map.put("b", 2); |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| assertTrue(json.contains("\"a\":1")); |
| assertTrue(json.contains("\"b\":2")); |
| } |
| |
| public void testMapDeserialization() { |
| String json = "{\"a\":1,\"b\":2}"; |
| Type typeOfMap = new TypeToken<Map<String,Integer>>(){}.getType(); |
| Map<String, Integer> target = gson.fromJson(json, typeOfMap); |
| assertEquals(1, target.get("a").intValue()); |
| assertEquals(2, target.get("b").intValue()); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testRawMapSerialization() { |
| Map map = new LinkedHashMap(); |
| map.put("a", 1); |
| map.put("b", "string"); |
| String json = gson.toJson(map); |
| assertTrue(json.contains("\"a\":1")); |
| assertTrue(json.contains("\"b\":\"string\"")); |
| } |
| |
| public void testMapSerializationEmpty() { |
| Map<String, Integer> map = new LinkedHashMap<String, Integer>(); |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| assertEquals("{}", json); |
| } |
| |
| public void testMapDeserializationEmpty() { |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| Map<String, Integer> map = gson.fromJson("{}", typeOfMap); |
| assertTrue(map.isEmpty()); |
| } |
| |
| public void testMapSerializationWithNullValue() { |
| Map<String, Integer> map = new LinkedHashMap<String, Integer>(); |
| map.put("abc", null); |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| |
| // Maps are represented as JSON objects, so ignoring null field |
| assertEquals("{}", json); |
| } |
| |
| public void testMapDeserializationWithNullValue() { |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| Map<String, Integer> map = gson.fromJson("{\"abc\":null}", typeOfMap); |
| assertEquals(1, map.size()); |
| assertNull(map.get("abc")); |
| } |
| |
| public void testMapSerializationWithNullValueButSerializeNulls() { |
| gson = new GsonBuilder().serializeNulls().create(); |
| Map<String, Integer> map = new LinkedHashMap<String, Integer>(); |
| map.put("abc", null); |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| |
| assertEquals("{\"abc\":null}", json); |
| } |
| |
| public void testMapSerializationWithNullKey() { |
| Map<String, Integer> map = new LinkedHashMap<String, Integer>(); |
| map.put(null, 123); |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| |
| assertEquals("{\"null\":123}", json); |
| } |
| |
| public void testMapDeserializationWithNullKey() { |
| Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType(); |
| Map<String, Integer> map = gson.fromJson("{\"null\":123}", typeOfMap); |
| assertEquals(1, map.size()); |
| assertNull(map.get(null)); |
| } |
| |
| public void testMapSerializationWithIntegerKeys() { |
| Map<Integer, String> map = new LinkedHashMap<Integer, String>(); |
| map.put(123, "456"); |
| Type typeOfMap = new TypeToken<Map<Integer, String>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| |
| assertEquals("{\"123\":\"456\"}", json); |
| } |
| |
| public void testMapDeserializationWithIntegerKeys() { |
| Type typeOfMap = new TypeToken<Map<Integer, String>>() {}.getType(); |
| Map<Integer, String> map = gson.fromJson("{\"123\":\"456\"}", typeOfMap); |
| assertEquals(1, map.size()); |
| assertTrue(map.containsKey(123)); |
| assertEquals("456", map.get(123)); |
| } |
| |
| public void testParameterizedMapSubclassSerialization() { |
| MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>(); |
| map.put("a", "b"); |
| Type type = new TypeToken<MyParameterizedMap<String, String>>() {}.getType(); |
| String json = gson.toJson(map, type); |
| assertTrue(json.contains("\"a\":\"b\"")); |
| } |
| |
| public void testParameterizedMapSubclassDeserialization() { |
| Type type = new TypeToken<MyParameterizedMap<String, Integer>>() {}.getType(); |
| String json = "{\"a\":1,\"b\":2}"; |
| MyParameterizedMap<String, Integer> map = gson.fromJson(json, type); |
| assertEquals(1, map.get("a").intValue()); |
| assertEquals(2, map.get("b").intValue()); |
| } |
| |
| private static class MyParameterizedMap<K, V> extends LinkedHashMap<K, V> { |
| private static final long serialVersionUID = 1L; |
| |
| @SuppressWarnings("unused") |
| int foo = 10; |
| } |
| |
| public void testMapSubclassSerialization() { |
| MyMap map = new MyMap(); |
| map.put("a", "b"); |
| String json = gson.toJson(map, MyMap.class); |
| assertTrue(json.contains("\"a\":\"b\"")); |
| } |
| |
| public void testMapStandardSubclassDeserialization() { |
| String json = "{a:'1',b:'2'}"; |
| Type type = new TypeToken<LinkedHashMap<String, String>>() {}.getType(); |
| LinkedHashMap<String, Integer> map = gson.fromJson(json, type); |
| assertEquals("1", map.get("a")); |
| assertEquals("2", map.get("b")); |
| } |
| |
| public void testMapSubclassDeserialization() { |
| Gson gson = new GsonBuilder().registerTypeAdapter(MyMap.class, new InstanceCreator<MyMap>() { |
| public MyMap createInstance(Type type) { |
| return new MyMap(); |
| } |
| }).create(); |
| String json = "{\"a\":1,\"b\":2}"; |
| MyMap map = gson.fromJson(json, MyMap.class); |
| assertEquals("1", map.get("a")); |
| assertEquals("2", map.get("b")); |
| } |
| |
| public void testCustomSerializerForSpecificMapType() { |
| Type type = $Gson$Types.newParameterizedTypeWithOwner( |
| null, Map.class, String.class, Long.class); |
| Gson gson = new GsonBuilder() |
| .registerTypeAdapter(type, new JsonSerializer<Map<String, Long>>() { |
| public JsonElement serialize(Map<String, Long> src, Type typeOfSrc, |
| JsonSerializationContext context) { |
| JsonArray array = new JsonArray(); |
| for (long value : src.values()) { |
| array.add(new JsonPrimitive(value)); |
| } |
| return array; |
| } |
| }).create(); |
| |
| Map<String, Long> src = new LinkedHashMap<String, Long>(); |
| src.put("one", 1L); |
| src.put("two", 2L); |
| src.put("three", 3L); |
| |
| assertEquals("[1,2,3]", gson.toJson(src, type)); |
| } |
| |
| /** |
| * Created in response to http://code.google.com/p/google-gson/issues/detail?id=99 |
| */ |
| private static class ClassWithAMap { |
| Map<String, String> map = new TreeMap<String, String>(); |
| } |
| |
| /** |
| * Created in response to http://code.google.com/p/google-gson/issues/detail?id=99 |
| */ |
| public void testMapSerializationWithNullValues() { |
| ClassWithAMap target = new ClassWithAMap(); |
| target.map.put("name1", null); |
| target.map.put("name2", "value2"); |
| String json = gson.toJson(target); |
| assertFalse(json.contains("name1")); |
| assertTrue(json.contains("name2")); |
| } |
| |
| /** |
| * Created in response to http://code.google.com/p/google-gson/issues/detail?id=99 |
| */ |
| public void testMapSerializationWithNullValuesSerialized() { |
| Gson gson = new GsonBuilder().serializeNulls().create(); |
| ClassWithAMap target = new ClassWithAMap(); |
| target.map.put("name1", null); |
| target.map.put("name2", "value2"); |
| String json = gson.toJson(target); |
| assertTrue(json.contains("name1")); |
| assertTrue(json.contains("name2")); |
| } |
| |
| public void testMapSerializationWithWildcardValues() { |
| Map<String, ? extends Collection<? extends Integer>> map = |
| new LinkedHashMap<String, Collection<Integer>>(); |
| map.put("test", null); |
| Type typeOfMap = |
| new TypeToken<Map<String, ? extends Collection<? extends Integer>>>() {}.getType(); |
| String json = gson.toJson(map, typeOfMap); |
| |
| assertEquals("{}", json); |
| } |
| |
| public void testMapDeserializationWithWildcardValues() { |
| Type typeOfMap = new TypeToken<Map<String, ? extends Long>>() {}.getType(); |
| Map<String, ? extends Long> map = gson.fromJson("{\"test\":123}", typeOfMap); |
| assertEquals(1, map.size()); |
| assertEquals(new Long(123L), map.get("test")); |
| } |
| |
| |
| private static class MyMap extends LinkedHashMap<String, String> { |
| private static final long serialVersionUID = 1L; |
| |
| @SuppressWarnings("unused") |
| int foo = 10; |
| } |
| |
| /** |
| * From bug report http://code.google.com/p/google-gson/issues/detail?id=95 |
| */ |
| public void testMapOfMapSerialization() { |
| Map<String, Map<String, String>> map = new HashMap<String, Map<String, String>>(); |
| Map<String, String> nestedMap = new HashMap<String, String>(); |
| nestedMap.put("1", "1"); |
| nestedMap.put("2", "2"); |
| map.put("nestedMap", nestedMap); |
| String json = gson.toJson(map); |
| assertTrue(json.contains("nestedMap")); |
| assertTrue(json.contains("\"1\":\"1\"")); |
| assertTrue(json.contains("\"2\":\"2\"")); |
| } |
| |
| /** |
| * From bug report http://code.google.com/p/google-gson/issues/detail?id=95 |
| */ |
| public void testMapOfMapDeserialization() { |
| String json = "{nestedMap:{'2':'2','1':'1'}}"; |
| Type type = new TypeToken<Map<String, Map<String, String>>>(){}.getType(); |
| Map<String, Map<String, String>> map = gson.fromJson(json, type); |
| Map<String, String> nested = map.get("nestedMap"); |
| assertEquals("1", nested.get("1")); |
| assertEquals("2", nested.get("2")); |
| } |
| |
| /** |
| * From bug report http://code.google.com/p/google-gson/issues/detail?id=178 |
| */ |
| public void testMapWithQuotes() { |
| Map<String, String> map = new HashMap<String, String>(); |
| map.put("a\"b", "c\"d"); |
| String json = gson.toJson(map); |
| assertEquals("{\"a\\\"b\":\"c\\\"d\"}", json); |
| } |
| |
| /** |
| * From issue 227. |
| */ |
| public void testWriteMapsWithEmptyStringKey() { |
| Map<String, Boolean> map = new HashMap<String, Boolean>(); |
| map.put("", true); |
| assertEquals("{\"\":true}", gson.toJson(map)); |
| |
| } |
| |
| public void testReadMapsWithEmptyStringKey() { |
| Map<String, Boolean> map = gson.fromJson("{\"\":true}", new TypeToken<Map<String, Boolean>>() {}.getType()); |
| assertEquals(Boolean.TRUE, map.get("")); |
| } |
| |
| /** |
| * From bug report http://code.google.com/p/google-gson/issues/detail?id=204 |
| */ |
| public void testSerializeMaps() { |
| Map<String, Object> map = new LinkedHashMap<String, Object>(); |
| map.put("a", 12); |
| map.put("b", null); |
| map.put("c", new HashMap<String, Object>()); |
| |
| assertEquals("{\"a\":12,\"b\":null,\"c\":{}}", |
| new GsonBuilder().serializeNulls().create().toJson(map)); |
| assertEquals("{\"a\":12,\"b\":null,\"c\":{}}", |
| new GsonBuilder().serializeNulls().create().toJson(map)); |
| assertEquals("{\"a\":12,\"c\":{}}", |
| new GsonBuilder().create().toJson(map)); |
| assertEquals("{\"a\":12,\"c\":{}}", |
| new GsonBuilder().create().toJson(map)); |
| } |
| |
| public final void testInterfaceTypeMap() { |
| MapClass element = new MapClass(); |
| TestTypes.Sub subType = new TestTypes.Sub(); |
| element.addBase("Test", subType); |
| element.addSub("Test", subType); |
| |
| String subTypeJson = new Gson().toJson(subType); |
| String expected = "{\"bases\":{\"Test\":" + subTypeJson + "}," |
| + "\"subs\":{\"Test\":" + subTypeJson + "}}"; |
| |
| Gson gsonWithComplexKeys = new GsonBuilder() |
| .enableComplexMapKeySerialization() |
| .create(); |
| String json = gsonWithComplexKeys.toJson(element); |
| assertEquals(expected, json); |
| |
| Gson gson = new Gson(); |
| json = gson.toJson(element); |
| assertEquals(expected, json); |
| } |
| |
| public final void testInterfaceTypeMapWithSerializer() { |
| MapClass element = new MapClass(); |
| TestTypes.Sub subType = new TestTypes.Sub(); |
| element.addBase("Test", subType); |
| element.addSub("Test", subType); |
| |
| Gson tempGson = new Gson(); |
| String subTypeJson = tempGson.toJson(subType); |
| final JsonElement baseTypeJson = tempGson.toJsonTree(subType, TestTypes.Base.class); |
| String expected = "{\"bases\":{\"Test\":" + baseTypeJson.toString() + "}," |
| + "\"subs\":{\"Test\":" + subTypeJson + "}}"; |
| |
| JsonSerializer<TestTypes.Base> baseTypeAdapter = new JsonSerializer<TestTypes.Base>() { |
| public JsonElement serialize(TestTypes.Base src, Type typeOfSrc, |
| JsonSerializationContext context) { |
| return baseTypeJson; |
| } |
| }; |
| |
| Gson gson = new GsonBuilder() |
| .enableComplexMapKeySerialization() |
| .registerTypeAdapter(TestTypes.Base.class, baseTypeAdapter) |
| .create(); |
| String json = gson.toJson(element); |
| assertEquals(expected, json); |
| |
| gson = new GsonBuilder() |
| .registerTypeAdapter(TestTypes.Base.class, baseTypeAdapter) |
| .create(); |
| json = gson.toJson(element); |
| assertEquals(expected, json); |
| } |
| |
| static final class MapClass { |
| private final Map<String, TestTypes.Base> bases = new HashMap<String, TestTypes.Base>(); |
| private final Map<String, TestTypes.Sub> subs = new HashMap<String, TestTypes.Sub>(); |
| |
| public final void addBase(final String name, final TestTypes.Base value) { |
| bases.put(name, value); |
| } |
| |
| public final void addSub(final String name, final TestTypes.Sub value) { |
| subs.put(name, value); |
| } |
| } |
| } |