• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.gson.functional;
18 
19 import com.google.gson.Gson;
20 import com.google.gson.GsonBuilder;
21 import com.google.gson.JsonDeserializationContext;
22 import com.google.gson.JsonDeserializer;
23 import com.google.gson.JsonElement;
24 import com.google.gson.JsonObject;
25 import com.google.gson.JsonParseException;
26 import com.google.gson.JsonPrimitive;
27 import com.google.gson.JsonSerializationContext;
28 import com.google.gson.JsonSerializer;
29 import java.lang.reflect.Type;
30 import junit.framework.TestCase;
31 
32 /**
33  * Test that the hierarchy adapter works when subtypes are used.
34  */
35 public final class TypeHierarchyAdapterTest extends TestCase {
36 
testTypeHierarchy()37   public void testTypeHierarchy() {
38     Manager andy = new Manager();
39     andy.userid = "andy";
40     andy.startDate = 2005;
41     andy.minions = new Employee[] {
42         new Employee("inder", 2007),
43         new Employee("joel", 2006),
44         new Employee("jesse", 2006),
45     };
46 
47     CEO eric = new CEO();
48     eric.userid = "eric";
49     eric.startDate = 2001;
50     eric.assistant = new Employee("jerome", 2006);
51 
52     eric.minions = new Employee[] {
53         new Employee("larry", 1998),
54         new Employee("sergey", 1998),
55         andy,
56     };
57 
58     Gson gson = new GsonBuilder()
59         .registerTypeHierarchyAdapter(Employee.class, new EmployeeAdapter())
60         .setPrettyPrinting()
61         .create();
62 
63     Company company = new Company();
64     company.ceo = eric;
65 
66     String json = gson.toJson(company, Company.class);
67     assertEquals("{\n" +
68         "  \"ceo\": {\n" +
69         "    \"userid\": \"eric\",\n" +
70         "    \"startDate\": 2001,\n" +
71         "    \"minions\": [\n" +
72         "      {\n" +
73         "        \"userid\": \"larry\",\n" +
74         "        \"startDate\": 1998\n" +
75         "      },\n" +
76         "      {\n" +
77         "        \"userid\": \"sergey\",\n" +
78         "        \"startDate\": 1998\n" +
79         "      },\n" +
80         "      {\n" +
81         "        \"userid\": \"andy\",\n" +
82         "        \"startDate\": 2005,\n" +
83         "        \"minions\": [\n" +
84         "          {\n" +
85         "            \"userid\": \"inder\",\n" +
86         "            \"startDate\": 2007\n" +
87         "          },\n" +
88         "          {\n" +
89         "            \"userid\": \"joel\",\n" +
90         "            \"startDate\": 2006\n" +
91         "          },\n" +
92         "          {\n" +
93         "            \"userid\": \"jesse\",\n" +
94         "            \"startDate\": 2006\n" +
95         "          }\n" +
96         "        ]\n" +
97         "      }\n" +
98         "    ],\n" +
99         "    \"assistant\": {\n" +
100         "      \"userid\": \"jerome\",\n" +
101         "      \"startDate\": 2006\n" +
102         "    }\n" +
103         "  }\n" +
104         "}", json);
105 
106     Company copied = gson.fromJson(json, Company.class);
107     assertEquals(json, gson.toJson(copied, Company.class));
108     assertEquals(copied.ceo.userid, company.ceo.userid);
109     assertEquals(copied.ceo.assistant.userid, company.ceo.assistant.userid);
110     assertEquals(copied.ceo.minions[0].userid, company.ceo.minions[0].userid);
111     assertEquals(copied.ceo.minions[1].userid, company.ceo.minions[1].userid);
112     assertEquals(copied.ceo.minions[2].userid, company.ceo.minions[2].userid);
113     assertEquals(((Manager) copied.ceo.minions[2]).minions[0].userid,
114         ((Manager) company.ceo.minions[2]).minions[0].userid);
115     assertEquals(((Manager) copied.ceo.minions[2]).minions[1].userid,
116         ((Manager) company.ceo.minions[2]).minions[1].userid);
117   }
118 
testRegisterSuperTypeFirst()119   public void testRegisterSuperTypeFirst() {
120     Gson gson = new GsonBuilder()
121         .registerTypeHierarchyAdapter(Employee.class, new EmployeeAdapter())
122         .registerTypeHierarchyAdapter(Manager.class, new ManagerAdapter())
123         .create();
124 
125     Manager manager = new Manager();
126     manager.userid = "inder";
127 
128     String json = gson.toJson(manager, Manager.class);
129     assertEquals("\"inder\"", json);
130     Manager copied = gson.fromJson(json, Manager.class);
131     assertEquals(manager.userid, copied.userid);
132   }
133 
134   /** This behaviour changed in Gson 2.1; it used to throw. */
testRegisterSubTypeFirstAllowed()135   public void testRegisterSubTypeFirstAllowed() {
136     new GsonBuilder()
137         .registerTypeHierarchyAdapter(Manager.class, new ManagerAdapter())
138         .registerTypeHierarchyAdapter(Employee.class, new EmployeeAdapter())
139         .create();
140   }
141 
142   static class ManagerAdapter implements JsonSerializer<Manager>, JsonDeserializer<Manager> {
deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)143     @Override public Manager deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
144       Manager result = new Manager();
145       result.userid = json.getAsString();
146       return result;
147     }
serialize(Manager src, Type typeOfSrc, JsonSerializationContext context)148     @Override public JsonElement serialize(Manager src, Type typeOfSrc, JsonSerializationContext context) {
149       return new JsonPrimitive(src.userid);
150     }
151   }
152 
153   static class EmployeeAdapter implements JsonSerializer<Employee>, JsonDeserializer<Employee> {
serialize(Employee employee, Type typeOfSrc, JsonSerializationContext context)154     @Override public JsonElement serialize(Employee employee, Type typeOfSrc,
155         JsonSerializationContext context) {
156       JsonObject result = new JsonObject();
157       result.add("userid", context.serialize(employee.userid, String.class));
158       result.add("startDate", context.serialize(employee.startDate, long.class));
159       if (employee instanceof Manager) {
160         result.add("minions", context.serialize(((Manager) employee).minions, Employee[].class));
161         if (employee instanceof CEO) {
162           result.add("assistant", context.serialize(((CEO) employee).assistant, Employee.class));
163         }
164       }
165       return result;
166     }
167 
deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)168     @Override public Employee deserialize(JsonElement json, Type typeOfT,
169         JsonDeserializationContext context) throws JsonParseException {
170       JsonObject object = json.getAsJsonObject();
171       Employee result = null;
172 
173       // if the employee has an assistant, she must be the CEO
174       JsonElement assistant = object.get("assistant");
175       if (assistant != null) {
176         result = new CEO();
177         ((CEO) result).assistant = context.deserialize(assistant, Employee.class);
178       }
179 
180       // only managers have minions
181       JsonElement minons = object.get("minions");
182       if (minons != null) {
183         if (result == null) {
184           result = new Manager();
185         }
186         ((Manager) result).minions = context.deserialize(minons, Employee[].class);
187       }
188 
189       if (result == null) {
190         result = new Employee();
191       }
192       result.userid = context.deserialize(object.get("userid"), String.class);
193       result.startDate = context.<Long>deserialize(object.get("startDate"), long.class);
194       return result;
195     }
196   }
197 
198   static class Employee {
199     String userid;
200     long startDate;
201 
Employee(String userid, long startDate)202     Employee(String userid, long startDate) {
203       this.userid = userid;
204       this.startDate = startDate;
205     }
206 
Employee()207     Employee() {}
208   }
209 
210   static class Manager extends Employee {
211     Employee[] minions;
212   }
213 
214   static class CEO extends Manager {
215     Employee assistant;
216   }
217 
218   static class Company {
219     CEO ceo;
220   }
221 }
222