From fd0f526fb06b6b8ac929e383894d2ce9508dbd36 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Wed, 19 Jan 2011 23:25:27 +0000 Subject: [PATCH] Basic functional test for type hierarchy adapter. --- .../functional/TypeHierarchyAdapterTest.java | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 gson/src/test/java/com/google/gson/functional/TypeHierarchyAdapterTest.java diff --git a/gson/src/test/java/com/google/gson/functional/TypeHierarchyAdapterTest.java b/gson/src/test/java/com/google/gson/functional/TypeHierarchyAdapterTest.java new file mode 100644 index 00000000..ecdd13d9 --- /dev/null +++ b/gson/src/test/java/com/google/gson/functional/TypeHierarchyAdapterTest.java @@ -0,0 +1,186 @@ +/* + * 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 com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import junit.framework.TestCase; + +/** + * Test that the hierarchy adapter works when subtypes are used. + */ +public final class TypeHierarchyAdapterTest extends TestCase { + + public void testTypeHierarchy() { + Manager andy = new Manager(); + andy.userid = "andy"; + andy.startDate = 2005; + andy.minions = new Employee[] { + new Employee("inder", 2007), + new Employee("joel", 2006), + new Employee("jesse", 2006), + }; + + CEO eric = new CEO(); + eric.userid = "eric"; + eric.startDate = 2001; + eric.assistant = new Employee("jerome", 2006); + + eric.minions = new Employee[] { + new Employee("larry", 1998), + new Employee("sergey", 1998), + andy, + }; + + Gson gson = new GsonBuilder() + .registerTypeHierarchyAdapter(Employee.class, new EmployeeAdapter()) + .setPrettyPrinting() + .create(); + + Company company = new Company(); + company.ceo = eric; + + String json = gson.toJson(company, Company.class); + assertEquals("{\n" + + " \"ceo\": {\n" + + " \"userid\": \"eric\",\n" + + " \"startDate\": 2001,\n" + + " \"minions\": [\n" + + " {\n" + + " \"userid\": \"larry\",\n" + + " \"startDate\": 1998\n" + + " },\n" + + " {\n" + + " \"userid\": \"sergey\",\n" + + " \"startDate\": 1998\n" + + " },\n" + + " {\n" + + " \"userid\": \"andy\",\n" + + " \"startDate\": 2005,\n" + + " \"minions\": [\n" + + " {\n" + + " \"userid\": \"inder\",\n" + + " \"startDate\": 2007\n" + + " },\n" + + " {\n" + + " \"userid\": \"joel\",\n" + + " \"startDate\": 2006\n" + + " },\n" + + " {\n" + + " \"userid\": \"jesse\",\n" + + " \"startDate\": 2006\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"assistant\": {\n" + + " \"userid\": \"jerome\",\n" + + " \"startDate\": 2006\n" + + " }\n" + + " }\n" + + "}", json); + + Company copied = gson.fromJson(json, Company.class); + assertEquals(json, gson.toJson(copied, Company.class)); + assertEquals(copied.ceo.userid, company.ceo.userid); + assertEquals(copied.ceo.assistant.userid, company.ceo.assistant.userid); + assertEquals(copied.ceo.minions[0].userid, company.ceo.minions[0].userid); + assertEquals(copied.ceo.minions[1].userid, company.ceo.minions[1].userid); + assertEquals(copied.ceo.minions[2].userid, company.ceo.minions[2].userid); + assertEquals(((Manager) copied.ceo.minions[2]).minions[0].userid, + ((Manager) company.ceo.minions[2]).minions[0].userid); + assertEquals(((Manager) copied.ceo.minions[2]).minions[1].userid, + ((Manager) company.ceo.minions[2]).minions[1].userid); + } + + static class EmployeeAdapter implements JsonSerializer, JsonDeserializer { + public JsonElement serialize(Employee employee, Type typeOfSrc, + JsonSerializationContext context) { + JsonObject result = new JsonObject(); + result.add("userid", context.serialize(employee.userid, String.class)); + result.add("startDate", context.serialize(employee.startDate, long.class)); + if (employee instanceof Manager) { + result.add("minions", context.serialize(((Manager) employee).minions, Employee[].class)); + if (employee instanceof CEO) { + result.add("assistant", context.serialize(((CEO) employee).assistant, Employee.class)); + } + } + return result; + } + + public Employee deserialize(JsonElement json, Type typeOfT, + JsonDeserializationContext context) throws JsonParseException { + JsonObject object = json.getAsJsonObject(); + Employee result = null; + + // if the employee has an assistant, she must be the CEO + JsonElement assistant = object.get("assistant"); + if (assistant != null) { + result = new CEO(); + ((CEO) result).assistant = context.deserialize(assistant, Employee.class); + } + + // only managers have minions + JsonElement minons = object.get("minions"); + if (minons != null) { + if (result == null) { + result = new Manager(); + } + ((Manager) result).minions = context.deserialize(minons, Employee[].class); + } + + if (result == null) { + result = new Employee(); + } + result.userid = context.deserialize(object.get("userid"), String.class); + result.startDate = context.deserialize(object.get("startDate"), long.class); + return result; + } + } + + static class Employee { + String userid; + long startDate; + + Employee(String userid, long startDate) { + this.userid = userid; + this.startDate = startDate; + } + + Employee() {} + } + + static class Manager extends Employee { + Employee[] minions; + } + + static class CEO extends Manager { + Employee assistant; + } + + static class Company { + CEO ceo; + } +}