/* * Copyright (C) 2011 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.google.gson.Gson; import com.google.gson.JsonObject; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.junit.Before; import org.junit.Test; /** * Tests for Gson serialization of a sub-class object while encountering a base-class type * * @author Inderjeet Singh */ @SuppressWarnings("unused") public class MoreSpecificTypeSerializationTest { private Gson gson; @Before public void setUp() throws Exception { gson = new Gson(); } @Test public void testSubclassFields() { ClassWithBaseFields target = new ClassWithBaseFields(new Sub(1, 2)); String json = gson.toJson(target); assertTrue(json.contains("\"b\":1")); assertTrue(json.contains("\"s\":2")); } @Test public void testListOfSubclassFields() { Collection list = new ArrayList<>(); list.add(new Base(1)); list.add(new Sub(2, 3)); ClassWithContainersOfBaseFields target = new ClassWithContainersOfBaseFields(list, null); String json = gson.toJson(target); assertTrue(json, json.contains("{\"b\":1}")); assertTrue(json, json.contains("{\"s\":3,\"b\":2}")); } @Test public void testMapOfSubclassFields() { Map map = new HashMap<>(); map.put("base", new Base(1)); map.put("sub", new Sub(2, 3)); ClassWithContainersOfBaseFields target = new ClassWithContainersOfBaseFields(null, map); JsonObject json = gson.toJsonTree(target).getAsJsonObject().get("map").getAsJsonObject(); assertEquals(1, json.get("base").getAsJsonObject().get("b").getAsInt()); JsonObject sub = json.get("sub").getAsJsonObject(); assertEquals(2, sub.get("b").getAsInt()); assertEquals(3, sub.get("s").getAsInt()); } /** * For parameterized type, Gson ignores the more-specific type and sticks to the declared type */ @Test public void testParameterizedSubclassFields() { ClassWithParameterizedBaseFields target = new ClassWithParameterizedBaseFields( new ParameterizedSub<>("one", "two")); String json = gson.toJson(target); assertTrue(json.contains("\"t\":\"one\"")); assertFalse(json.contains("\"s\"")); } /** * For parameterized type in a List, Gson ignores the more-specific type and sticks to * the declared type */ @Test public void testListOfParameterizedSubclassFields() { Collection> list = new ArrayList<>(); list.add(new ParameterizedBase<>("one")); list.add(new ParameterizedSub<>("two", "three")); ClassWithContainersOfParameterizedBaseFields target = new ClassWithContainersOfParameterizedBaseFields(list, null); String json = gson.toJson(target); assertTrue(json, json.contains("{\"t\":\"one\"}")); assertFalse(json, json.contains("\"s\":")); } /** * For parameterized type in a map, Gson ignores the more-specific type and sticks to the * declared type */ @Test public void testMapOfParameterizedSubclassFields() { Map> map = new HashMap<>(); map.put("base", new ParameterizedBase<>("one")); map.put("sub", new ParameterizedSub<>("two", "three")); ClassWithContainersOfParameterizedBaseFields target = new ClassWithContainersOfParameterizedBaseFields(null, map); JsonObject json = gson.toJsonTree(target).getAsJsonObject().get("map").getAsJsonObject(); assertEquals("one", json.get("base").getAsJsonObject().get("t").getAsString()); JsonObject sub = json.get("sub").getAsJsonObject(); assertEquals("two", sub.get("t").getAsString()); assertNull(sub.get("s")); } private static class Base { int b; Base(int b) { this.b = b; } } private static class Sub extends Base { int s; Sub(int b, int s) { super(b); this.s = s; } } private static class ClassWithBaseFields { Base b; ClassWithBaseFields(Base b) { this.b = b; } } private static class ClassWithContainersOfBaseFields { Collection collection; Map map; ClassWithContainersOfBaseFields(Collection collection, Map map) { this.collection = collection; this.map = map; } } private static class ParameterizedBase { T t; ParameterizedBase(T t) { this.t = t; } } private static class ParameterizedSub extends ParameterizedBase { T s; ParameterizedSub(T t, T s) { super(t); this.s = s; } } private static class ClassWithParameterizedBaseFields { ParameterizedBase b; ClassWithParameterizedBaseFields(ParameterizedBase b) { this.b = b; } } private static class ClassWithContainersOfParameterizedBaseFields { Collection> collection; Map> map; ClassWithContainersOfParameterizedBaseFields(Collection> collection, Map> map) { this.collection = collection; this.map = map; } } }