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 static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 22 import com.google.gson.Gson; 23 import com.google.gson.GsonBuilder; 24 import com.google.gson.JsonDeserializationContext; 25 import com.google.gson.JsonDeserializer; 26 import com.google.gson.JsonElement; 27 import com.google.gson.JsonParseException; 28 import com.google.gson.JsonPrimitive; 29 import com.google.gson.JsonSerializationContext; 30 import com.google.gson.JsonSerializer; 31 import com.google.gson.reflect.TypeToken; 32 import java.lang.reflect.ParameterizedType; 33 import java.lang.reflect.Type; 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.List; 37 import org.junit.Before; 38 import org.junit.Test; 39 40 /** 41 * Collection of functional tests for DOM tree based type adapters. 42 */ 43 public class TreeTypeAdaptersTest { 44 private static final Id<Student> STUDENT1_ID = new Id<>("5", Student.class); 45 private static final Id<Student> STUDENT2_ID = new Id<>("6", Student.class); 46 private static final Student STUDENT1 = new Student(STUDENT1_ID, "first"); 47 private static final Student STUDENT2 = new Student(STUDENT2_ID, "second"); 48 private static final Type TYPE_COURSE_HISTORY = 49 new TypeToken<Course<HistoryCourse>>(){}.getType(); 50 private static final Id<Course<HistoryCourse>> COURSE_ID = 51 new Id<>("10", TYPE_COURSE_HISTORY); 52 53 private Gson gson; 54 private Course<HistoryCourse> course; 55 56 @Before setUp()57 public void setUp() { 58 gson = new GsonBuilder() 59 .registerTypeAdapter(Id.class, new IdTreeTypeAdapter()) 60 .create(); 61 course = new Course<>(COURSE_ID, 4, 62 new Assignment<HistoryCourse>(null, null), Arrays.asList(STUDENT1, STUDENT2)); 63 } 64 65 @Test testSerializeId()66 public void testSerializeId() { 67 String json = gson.toJson(course, TYPE_COURSE_HISTORY); 68 assertTrue(json.contains(String.valueOf(COURSE_ID.getValue()))); 69 assertTrue(json.contains(String.valueOf(STUDENT1_ID.getValue()))); 70 assertTrue(json.contains(String.valueOf(STUDENT2_ID.getValue()))); 71 } 72 73 @Test testDeserializeId()74 public void testDeserializeId() { 75 String json = "{courseId:1,students:[{id:1,name:'first'},{id:6,name:'second'}]," 76 + "numAssignments:4,assignment:{}}"; 77 Course<HistoryCourse> target = gson.fromJson(json, TYPE_COURSE_HISTORY); 78 assertEquals("1", target.getStudents().get(0).id.getValue()); 79 assertEquals("6", target.getStudents().get(1).id.getValue()); 80 assertEquals("1", target.getId().getValue()); 81 } 82 83 private static final class Id<R> { 84 final String value; 85 @SuppressWarnings("unused") 86 final Type typeOfId; 87 Id(String value, Type typeOfId)88 private Id(String value, Type typeOfId) { 89 this.value = value; 90 this.typeOfId = typeOfId; 91 } getValue()92 public String getValue() { 93 return value; 94 } 95 } 96 97 private static final class IdTreeTypeAdapter implements JsonSerializer<Id<?>>, 98 JsonDeserializer<Id<?>> { 99 100 @Override deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)101 public Id<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 102 throws JsonParseException { 103 if (!(typeOfT instanceof ParameterizedType)) { 104 throw new JsonParseException("Id of unknown type: " + typeOfT); 105 } 106 ParameterizedType parameterizedType = (ParameterizedType) typeOfT; 107 // Since Id takes only one TypeVariable, the actual type corresponding to the first 108 // TypeVariable is the Type we are looking for 109 Type typeOfId = parameterizedType.getActualTypeArguments()[0]; 110 return new Id<>(json.getAsString(), typeOfId); 111 } 112 113 @Override serialize(Id<?> src, Type typeOfSrc, JsonSerializationContext context)114 public JsonElement serialize(Id<?> src, Type typeOfSrc, JsonSerializationContext context) { 115 return new JsonPrimitive(src.getValue()); 116 } 117 } 118 119 @SuppressWarnings("unused") 120 private static class Student { 121 Id<Student> id; 122 String name; 123 Student()124 private Student() { 125 this(null, null); 126 } Student(Id<Student> id, String name)127 public Student(Id<Student> id, String name) { 128 this.id = id; 129 this.name = name; 130 } 131 } 132 133 @SuppressWarnings("unused") 134 private static class Course<T> { 135 final List<Student> students; 136 private final Id<Course<T>> courseId; 137 private final int numAssignments; 138 private final Assignment<T> assignment; 139 Course()140 private Course() { 141 this(null, 0, null, new ArrayList<Student>()); 142 } 143 Course(Id<Course<T>> courseId, int numAssignments, Assignment<T> assignment, List<Student> players)144 public Course(Id<Course<T>> courseId, int numAssignments, 145 Assignment<T> assignment, List<Student> players) { 146 this.courseId = courseId; 147 this.numAssignments = numAssignments; 148 this.assignment = assignment; 149 this.students = players; 150 } getId()151 public Id<Course<T>> getId() { 152 return courseId; 153 } getStudents()154 List<Student> getStudents() { 155 return students; 156 } 157 } 158 159 @SuppressWarnings("unused") 160 private static class Assignment<T> { 161 private final Id<Assignment<T>> id; 162 private final T data; 163 Assignment()164 private Assignment() { 165 this(null, null); 166 } Assignment(Id<Assignment<T>> id, T data)167 public Assignment(Id<Assignment<T>> id, T data) { 168 this.id = id; 169 this.data = data; 170 } 171 } 172 173 @SuppressWarnings("unused") 174 private static class HistoryCourse { 175 int numClasses; 176 } 177 } 178