1 /* 2 * Copyright (C) 2008 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.common; 18 19 import com.google.gson.JsonDeserializationContext; 20 import com.google.gson.JsonDeserializer; 21 import com.google.gson.JsonElement; 22 import com.google.gson.JsonObject; 23 import com.google.gson.JsonParseException; 24 import com.google.gson.JsonPrimitive; 25 import com.google.gson.JsonSerializationContext; 26 import com.google.gson.JsonSerializer; 27 import com.google.gson.annotations.SerializedName; 28 import java.lang.reflect.Type; 29 import java.util.Collection; 30 31 /** 32 * Types used for testing JSON serialization and deserialization 33 * 34 * @author Inderjeet Singh 35 * @author Joel Leitch 36 */ 37 public class TestTypes { 38 39 public static class Base { 40 public static final String BASE_NAME = Base.class.getSimpleName(); 41 public static final String BASE_FIELD_KEY = "baseName"; 42 public static final String SERIALIZER_KEY = "serializerName"; 43 public String baseName = BASE_NAME; 44 public String serializerName; 45 } 46 47 public static class Sub extends Base { 48 public static final String SUB_NAME = Sub.class.getSimpleName(); 49 public static final String SUB_FIELD_KEY = "subName"; 50 public final String subName = SUB_NAME; 51 } 52 53 public static class ClassWithBaseField { 54 public static final String FIELD_KEY = "base"; 55 public final Base base; ClassWithBaseField(Base base)56 public ClassWithBaseField(Base base) { 57 this.base = base; 58 } 59 } 60 61 public static class ClassWithBaseArrayField { 62 public static final String FIELD_KEY = "base"; 63 public final Base[] base; ClassWithBaseArrayField(Base[] base)64 public ClassWithBaseArrayField(Base[] base) { 65 this.base = base; 66 } 67 } 68 69 public static class ClassWithBaseCollectionField { 70 public static final String FIELD_KEY = "base"; 71 public final Collection<Base> base; ClassWithBaseCollectionField(Collection<Base> base)72 public ClassWithBaseCollectionField(Collection<Base> base) { 73 this.base = base; 74 } 75 } 76 77 public static class BaseSerializer implements JsonSerializer<Base> { 78 public static final String NAME = BaseSerializer.class.getSimpleName(); 79 @Override serialize(Base src, Type typeOfSrc, JsonSerializationContext context)80 public JsonElement serialize(Base src, Type typeOfSrc, JsonSerializationContext context) { 81 JsonObject obj = new JsonObject(); 82 obj.addProperty(Base.SERIALIZER_KEY, NAME); 83 return obj; 84 } 85 } 86 public static class SubSerializer implements JsonSerializer<Sub> { 87 public static final String NAME = SubSerializer.class.getSimpleName(); 88 @Override serialize(Sub src, Type typeOfSrc, JsonSerializationContext context)89 public JsonElement serialize(Sub src, Type typeOfSrc, JsonSerializationContext context) { 90 JsonObject obj = new JsonObject(); 91 obj.addProperty(Base.SERIALIZER_KEY, NAME); 92 return obj; 93 } 94 } 95 96 public static class StringWrapper { 97 public final String someConstantStringInstanceField; 98 StringWrapper(String value)99 public StringWrapper(String value) { 100 someConstantStringInstanceField = value; 101 } 102 } 103 104 public static class BagOfPrimitives { 105 public static final long DEFAULT_VALUE = 0; 106 public long longValue; 107 public int intValue; 108 public boolean booleanValue; 109 public String stringValue; 110 BagOfPrimitives()111 public BagOfPrimitives() { 112 this(DEFAULT_VALUE, 0, false, ""); 113 } 114 BagOfPrimitives(long longValue, int intValue, boolean booleanValue, String stringValue)115 public BagOfPrimitives(long longValue, int intValue, boolean booleanValue, String stringValue) { 116 this.longValue = longValue; 117 this.intValue = intValue; 118 this.booleanValue = booleanValue; 119 this.stringValue = stringValue; 120 } 121 getIntValue()122 public int getIntValue() { 123 return intValue; 124 } 125 getExpectedJson()126 public String getExpectedJson() { 127 StringBuilder sb = new StringBuilder(); 128 sb.append("{"); 129 sb.append("\"longValue\":").append(longValue).append(","); 130 sb.append("\"intValue\":").append(intValue).append(","); 131 sb.append("\"booleanValue\":").append(booleanValue).append(","); 132 sb.append("\"stringValue\":\"").append(stringValue).append("\""); 133 sb.append("}"); 134 return sb.toString(); 135 } 136 137 @Override hashCode()138 public int hashCode() { 139 final int prime = 31; 140 int result = 1; 141 result = prime * result + (booleanValue ? 1231 : 1237); 142 result = prime * result + intValue; 143 result = prime * result + (int) (longValue ^ (longValue >>> 32)); 144 result = prime * result + ((stringValue == null) ? 0 : stringValue.hashCode()); 145 return result; 146 } 147 148 @Override equals(Object obj)149 public boolean equals(Object obj) { 150 if (this == obj) 151 return true; 152 if (obj == null) 153 return false; 154 if (getClass() != obj.getClass()) 155 return false; 156 BagOfPrimitives other = (BagOfPrimitives) obj; 157 if (booleanValue != other.booleanValue) 158 return false; 159 if (intValue != other.intValue) 160 return false; 161 if (longValue != other.longValue) 162 return false; 163 if (stringValue == null) { 164 if (other.stringValue != null) 165 return false; 166 } else if (!stringValue.equals(other.stringValue)) 167 return false; 168 return true; 169 } 170 171 @Override toString()172 public String toString() { 173 return String.format("(longValue=%d,intValue=%d,booleanValue=%b,stringValue=%s)", 174 longValue, intValue, booleanValue, stringValue); 175 } 176 } 177 178 public static class BagOfPrimitiveWrappers { 179 private final Long longValue; 180 private final Integer intValue; 181 private final Boolean booleanValue; 182 BagOfPrimitiveWrappers(Long longValue, Integer intValue, Boolean booleanValue)183 public BagOfPrimitiveWrappers(Long longValue, Integer intValue, Boolean booleanValue) { 184 this.longValue = longValue; 185 this.intValue = intValue; 186 this.booleanValue = booleanValue; 187 } 188 getExpectedJson()189 public String getExpectedJson() { 190 StringBuilder sb = new StringBuilder(); 191 sb.append("{"); 192 sb.append("\"longValue\":").append(longValue).append(","); 193 sb.append("\"intValue\":").append(intValue).append(","); 194 sb.append("\"booleanValue\":").append(booleanValue); 195 sb.append("}"); 196 return sb.toString(); 197 } 198 } 199 200 public static class PrimitiveArray { 201 private final long[] longArray; 202 PrimitiveArray()203 public PrimitiveArray() { 204 this(new long[0]); 205 } 206 PrimitiveArray(long[] longArray)207 public PrimitiveArray(long[] longArray) { 208 this.longArray = longArray; 209 } 210 getExpectedJson()211 public String getExpectedJson() { 212 StringBuilder sb = new StringBuilder(); 213 sb.append("{\"longArray\":["); 214 215 boolean first = true; 216 for (long l : longArray) { 217 if (!first) { 218 sb.append(","); 219 } else { 220 first = false; 221 } 222 sb.append(l); 223 } 224 225 sb.append("]}"); 226 return sb.toString(); 227 } 228 } 229 230 @SuppressWarnings("overrides") // for missing hashCode() override 231 public static class ClassWithNoFields { 232 // Nothing here.. 233 @Override equals(Object other)234 public boolean equals(Object other) { 235 return other.getClass() == ClassWithNoFields.class; 236 } 237 } 238 239 public static class Nested { 240 private final BagOfPrimitives primitive1; 241 private final BagOfPrimitives primitive2; 242 Nested()243 public Nested() { 244 this(null, null); 245 } 246 Nested(BagOfPrimitives primitive1, BagOfPrimitives primitive2)247 public Nested(BagOfPrimitives primitive1, BagOfPrimitives primitive2) { 248 this.primitive1 = primitive1; 249 this.primitive2 = primitive2; 250 } 251 getExpectedJson()252 public String getExpectedJson() { 253 StringBuilder sb = new StringBuilder(); 254 sb.append("{"); 255 appendFields(sb); 256 sb.append("}"); 257 return sb.toString(); 258 } 259 appendFields(StringBuilder sb)260 public void appendFields(StringBuilder sb) { 261 if (primitive1 != null) { 262 sb.append("\"primitive1\":").append(primitive1.getExpectedJson()); 263 } 264 if (primitive1 != null && primitive2 != null) { 265 sb.append(","); 266 } 267 if (primitive2 != null) { 268 sb.append("\"primitive2\":").append(primitive2.getExpectedJson()); 269 } 270 } 271 } 272 273 public static class ClassWithTransientFields<T> { 274 public transient T transientT; 275 public final transient long transientLongValue; 276 private final long[] longValue; 277 ClassWithTransientFields()278 public ClassWithTransientFields() { 279 this(0L); 280 } 281 ClassWithTransientFields(long value)282 public ClassWithTransientFields(long value) { 283 longValue = new long[] { value }; 284 transientLongValue = value + 1; 285 } 286 getExpectedJson()287 public String getExpectedJson() { 288 StringBuilder sb = new StringBuilder(); 289 sb.append("{"); 290 sb.append("\"longValue\":[").append(longValue[0]).append("]"); 291 sb.append("}"); 292 return sb.toString(); 293 } 294 } 295 296 public static class ClassWithCustomTypeConverter { 297 private final BagOfPrimitives bag; 298 private final int value; 299 ClassWithCustomTypeConverter()300 public ClassWithCustomTypeConverter() { 301 this(new BagOfPrimitives(), 10); 302 } 303 ClassWithCustomTypeConverter(int value)304 public ClassWithCustomTypeConverter(int value) { 305 this(new BagOfPrimitives(value, value, false, ""), value); 306 } 307 ClassWithCustomTypeConverter(BagOfPrimitives bag, int value)308 public ClassWithCustomTypeConverter(BagOfPrimitives bag, int value) { 309 this.bag = bag; 310 this.value = value; 311 } 312 getBag()313 public BagOfPrimitives getBag() { 314 return bag; 315 } 316 getExpectedJson()317 public String getExpectedJson() { 318 return "{\"url\":\"" + bag.getExpectedJson() + "\",\"value\":" + value + "}"; 319 } 320 getValue()321 public int getValue() { 322 return value; 323 } 324 } 325 326 public static class ArrayOfObjects { 327 private final BagOfPrimitives[] elements; ArrayOfObjects()328 public ArrayOfObjects() { 329 elements = new BagOfPrimitives[3]; 330 for (int i = 0; i < elements.length; ++i) { 331 elements[i] = new BagOfPrimitives(i, i+2, false, "i"+i); 332 } 333 } getExpectedJson()334 public String getExpectedJson() { 335 StringBuilder sb = new StringBuilder("{\"elements\":["); 336 boolean first = true; 337 for (BagOfPrimitives element : elements) { 338 if (first) { 339 first = false; 340 } else { 341 sb.append(","); 342 } 343 sb.append(element.getExpectedJson()); 344 } 345 sb.append("]}"); 346 return sb.toString(); 347 } 348 } 349 350 public static class ClassOverridingEquals { 351 public ClassOverridingEquals ref; 352 getExpectedJson()353 public String getExpectedJson() { 354 if (ref == null) { 355 return "{}"; 356 } 357 return "{\"ref\":" + ref.getExpectedJson() + "}"; 358 } 359 @Override equals(Object obj)360 public boolean equals(Object obj) { 361 return true; 362 } 363 364 @Override hashCode()365 public int hashCode() { 366 return 1; 367 } 368 } 369 370 public static class ClassWithArray { 371 public final Object[] array; ClassWithArray()372 public ClassWithArray() { 373 array = null; 374 } 375 ClassWithArray(Object[] array)376 public ClassWithArray(Object[] array) { 377 this.array = array; 378 } 379 } 380 381 public static class ClassWithObjects { 382 public final BagOfPrimitives bag; ClassWithObjects()383 public ClassWithObjects() { 384 this(new BagOfPrimitives()); 385 } ClassWithObjects(BagOfPrimitives bag)386 public ClassWithObjects(BagOfPrimitives bag) { 387 this.bag = bag; 388 } 389 } 390 391 public static class ClassWithSerializedNameFields { 392 @SerializedName("fooBar") public final int f; 393 @SerializedName("Another Foo") public final int g; 394 ClassWithSerializedNameFields()395 public ClassWithSerializedNameFields() { 396 this(1, 4); 397 } ClassWithSerializedNameFields(int f, int g)398 public ClassWithSerializedNameFields(int f, int g) { 399 this.f = f; 400 this.g = g; 401 } 402 getExpectedJson()403 public String getExpectedJson() { 404 return '{' + "\"fooBar\":" + f + ",\"Another Foo\":" + g + '}'; 405 } 406 } 407 408 public static class CrazyLongTypeAdapter 409 implements JsonSerializer<Long>, JsonDeserializer<Long> { 410 public static final long DIFFERENCE = 5L; 411 @Override serialize(Long src, Type typeOfSrc, JsonSerializationContext context)412 public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) { 413 return new JsonPrimitive(src + DIFFERENCE); 414 } 415 @Override deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)416 public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 417 throws JsonParseException { 418 return json.getAsLong() - DIFFERENCE; 419 } 420 } 421 } 422