gson-comments/gson/src/test/java/com/google/gson/functional/ObjectTest.java

536 lines
18 KiB
Java

/*
* Copyright (C) 2008 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.InstanceCreator;
import com.google.gson.JsonParseException;
import com.google.gson.common.TestTypes.ArrayOfObjects;
import com.google.gson.common.TestTypes.BagOfPrimitiveWrappers;
import com.google.gson.common.TestTypes.BagOfPrimitives;
import com.google.gson.common.TestTypes.ClassOverridingEquals;
import com.google.gson.common.TestTypes.ClassWithArray;
import com.google.gson.common.TestTypes.ClassWithNoFields;
import com.google.gson.common.TestTypes.ClassWithObjects;
import com.google.gson.common.TestTypes.ClassWithTransientFields;
import com.google.gson.common.TestTypes.MyEnum;
import com.google.gson.common.TestTypes.Nested;
import com.google.gson.common.TestTypes.PrimitiveArray;
import junit.framework.TestCase;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Functional tests for Json serialization and deserialization of regular classes.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public class ObjectTest extends TestCase {
private Gson gson;
@Override
protected void setUp() throws Exception {
super.setUp();
gson = new Gson();
}
public void testJsonInSingleQuotesDeserialization() {
String json = "{'stringValue':'no message','intValue':10,'longValue':20}";
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals("no message", target.stringValue);
assertEquals(10, target.intValue);
assertEquals(20, target.longValue);
}
public void testJsonInMixedQuotesDeserialization() {
String json = "{\"stringValue\":'no message','intValue':10,'longValue':20}";
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals("no message", target.stringValue);
assertEquals(10, target.intValue);
assertEquals(20, target.longValue);
}
public void testBagOfPrimitivesSerialization() throws Exception {
BagOfPrimitives target = new BagOfPrimitives(10, 20, false, "stringValue");
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testBagOfPrimitivesDeserialization() throws Exception {
BagOfPrimitives src = new BagOfPrimitives(10, 20, false, "stringValue");
String json = src.getExpectedJson();
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals(json, target.getExpectedJson());
}
public void testBagOfPrimitiveWrappersSerialization() throws Exception {
BagOfPrimitiveWrappers target = new BagOfPrimitiveWrappers(10L, 20, false);
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testBagOfPrimitiveWrappersDeserialization() throws Exception {
BagOfPrimitiveWrappers target = new BagOfPrimitiveWrappers(10L, 20, false);
String jsonString = target.getExpectedJson();
target = gson.fromJson(jsonString, BagOfPrimitiveWrappers.class);
assertEquals(jsonString, target.getExpectedJson());
}
public void testDirectedAcyclicGraphSerialization() throws Exception {
ContainsReferenceToSelfType a = new ContainsReferenceToSelfType();
ContainsReferenceToSelfType b = new ContainsReferenceToSelfType();
ContainsReferenceToSelfType c = new ContainsReferenceToSelfType();
a.children.add(b);
a.children.add(c);
b.children.add(c);
assertNotNull(gson.toJson(a));
}
public void testDirectedAcyclicGraphDeserialization() throws Exception {
String json = "{\"children\":[{\"children\":[{\"children\":[]}]},{\"children\":[]}]}";
ContainsReferenceToSelfType target = gson.fromJson(json, ContainsReferenceToSelfType.class);
assertNotNull(target);
assertEquals(2, target.children.size());
}
public void testClassWithTransientFieldsSerialization() throws Exception {
ClassWithTransientFields target = new ClassWithTransientFields(1L);
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testClassWithTransientFieldsDeserialization() throws Exception {
String json = "{\"longValue\":[1]}";
ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class);
assertEquals(json, target.getExpectedJson());
}
public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored()
throws Exception {
String json = "{\"transientLongValue\":1,\"longValue\":[1]}";
ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class);
assertFalse(target.transientLongValue != 1);
}
public void testClassWithNoFieldsSerialization() throws Exception {
assertEquals("{}", gson.toJson(new ClassWithNoFields()));
}
public void testClassWithNoFieldsDeserialization() throws Exception {
String json = "{}";
ClassWithNoFields target = gson.fromJson(json, ClassWithNoFields.class);
ClassWithNoFields expected = new ClassWithNoFields();
assertEquals(expected, target);
}
public void testNestedSerialization() throws Exception {
Nested target = new Nested(new BagOfPrimitives(10, 20, false, "stringValue"),
new BagOfPrimitives(30, 40, true, "stringValue"));
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testNestedDeserialization() throws Exception {
String json = "{\"primitive1\":{\"longValue\":10,\"intValue\":20,\"booleanValue\":false,"
+ "\"stringValue\":\"stringValue\"},\"primitive2\":{\"longValue\":30,\"intValue\":40,"
+ "\"booleanValue\":true,\"stringValue\":\"stringValue\"}}";
Nested target = gson.fromJson(json, Nested.class);
assertEquals(json, target.getExpectedJson());
}
public void testInheritenceSerialization() throws Exception {
SubTypeOfNested target = new SubTypeOfNested(new BagOfPrimitives(10, 20, false, "stringValue"),
new BagOfPrimitives(30, 40, true, "stringValue"));
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testInheritenceDeserialization() throws Exception {
String json = "{\"value\":5,\"primitive1\":{\"longValue\":10,\"intValue\":20,"
+ "\"booleanValue\":false,\"stringValue\":\"stringValue\"},\"primitive2\":"
+ "{\"longValue\":30,\"intValue\":40,\"booleanValue\":true,"
+ "\"stringValue\":\"stringValue\"}}";
SubTypeOfNested target = gson.fromJson(json, SubTypeOfNested.class);
assertEquals(json, target.getExpectedJson());
}
public void testNullSerialization() throws Exception {
assertEquals("", gson.toJson(null));
}
public void testNullDeserialization() throws Exception {
try {
gson.fromJson("", Object.class);
fail("Null strings should not be allowed");
} catch (JsonParseException expected) {
}
}
public void testNullFieldsSerialization() throws Exception {
Nested target = new Nested(new BagOfPrimitives(10, 20, false, "stringValue"), null);
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testNullFieldsDeserialization() throws Exception {
String json = "{\"primitive1\":{\"longValue\":10,\"intValue\":20,\"booleanValue\":false"
+ ",\"stringValue\":\"stringValue\"}}";
Nested target = gson.fromJson(json, Nested.class);
assertEquals(json, target.getExpectedJson());
}
public void testArrayOfObjectsSerialization() throws Exception {
ArrayOfObjects target = new ArrayOfObjects();
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testArrayOfObjectsDeserialization() throws Exception {
String json = new ArrayOfObjects().getExpectedJson();
ArrayOfObjects target = gson.fromJson(json, ArrayOfObjects.class);
assertEquals(json, target.getExpectedJson());
}
public void testArrayOfArraysSerialization() throws Exception {
ArrayOfArrays target = new ArrayOfArrays();
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testArrayOfArraysDeserialization() throws Exception {
String json = new ArrayOfArrays().getExpectedJson();
ArrayOfArrays target = gson.fromJson(json, ArrayOfArrays.class);
assertEquals(json, target.getExpectedJson());
}
public void testClassWithEnumFieldSerialization() throws Exception {
ClassWithEnumFields target = new ClassWithEnumFields();
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testClassWithEnumFieldDeserialization() throws Exception {
String json = new ClassWithEnumFields().getExpectedJson();
ClassWithEnumFields target = gson.fromJson(json, ClassWithEnumFields.class);
assertEquals(json, target.getExpectedJson());
}
public void testTopLevelEnumSerialization() throws Exception {
MyEnum target = MyEnum.VALUE1;
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testTopLevelEnumDeserialization() throws Exception {
String json = MyEnum.VALUE1.getExpectedJson();
MyEnum target = gson.fromJson(json, MyEnum.class);
assertEquals(json, target.getExpectedJson());
}
public void testSubInterfacesOfCollectionSerialization() throws Exception {
List<Integer> list = new LinkedList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
Queue<Long> queue = new LinkedList<Long>();
queue.add(0L);
queue.add(1L);
queue.add(2L);
queue.add(3L);
Set<Float> set = new TreeSet<Float>();
set.add(0.1F);
set.add(0.2F);
set.add(0.3F);
set.add(0.4F);
SortedSet<Character> sortedSet = new TreeSet<Character>();
sortedSet.add('a');
sortedSet.add('b');
sortedSet.add('c');
sortedSet.add('d');
ClassWithSubInterfacesOfCollection target =
new ClassWithSubInterfacesOfCollection(list, queue, set, sortedSet);
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
public void testSubInterfacesOfCollectionDeserialization() throws Exception {
String json = "{\"list\":[0,1,2,3],\"queue\":[0,1,2,3],\"set\":[0.1,0.2,0.3,0.4],"
+ "\"sortedSet\":[\"a\",\"b\",\"c\",\"d\"]"
// + ",\"navigableSet\":[\"abc\",\"def\",\"ghi\",\"jkl\"]"
+ "}";
ClassWithSubInterfacesOfCollection target = gson.fromJson(
json, ClassWithSubInterfacesOfCollection.class);
assertEquals(json, target.getExpectedJson());
}
/**
* Created in response to Issue 14: http://code.google.com/p/google-gson/issues/detail?id=14
*/
public void testNullArraysDeserialization() throws Exception {
String json = "{\"array\": null}";
ClassWithArray target = gson.fromJson(json, ClassWithArray.class);
assertNull(target.array);
}
/**
* Created in response to Issue 14: http://code.google.com/p/google-gson/issues/detail?id=14
*/
public void testNullObjectFieldsDeserialization() throws Exception {
String json = "{\"bag\": null}";
ClassWithObjects target = gson.fromJson(json, ClassWithObjects.class);
assertNull(target.bag);
}
public void testEmptyCollectionInAnObjectDeserialization() throws Exception {
String json = "{\"children\":[]}";
ContainsReferenceToSelfType target = gson.fromJson(json, ContainsReferenceToSelfType.class);
assertNotNull(target);
assertTrue(target.children.isEmpty());
}
public void testPrimitiveArrayInAnObjectDeserialization() throws Exception {
String json = "{\"longArray\":[0,1,2,3,4,5,6,7,8,9]}";
PrimitiveArray target = gson.fromJson(json, PrimitiveArray.class);
assertEquals(json, target.getExpectedJson());
}
/**
* Created in response to Issue 14: http://code.google.com/p/google-gson/issues/detail?id=14
*/
public void testNullPrimitiveFieldsDeserialization() throws Exception {
String json = "{\"longValue\":null}";
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals(BagOfPrimitives.DEFAULT_VALUE, target.longValue);
}
public void testEmptyCollectionInAnObjectSerialization() throws Exception {
ContainsReferenceToSelfType target = new ContainsReferenceToSelfType();
assertEquals("{\"children\":[]}", gson.toJson(target));
}
public void testCircularSerialization() throws Exception {
ContainsReferenceToSelfType a = new ContainsReferenceToSelfType();
ContainsReferenceToSelfType b = new ContainsReferenceToSelfType();
a.children.add(b);
b.children.add(a);
try {
gson.toJson(a);
fail("Circular types should not get printed!");
} catch (IllegalStateException expected) { }
}
public void testSelfReferenceSerialization() throws Exception {
ClassOverridingEquals objA = new ClassOverridingEquals();
objA.ref = objA;
try {
gson.toJson(objA);
fail("Circular reference to self can not be serialized!");
} catch (IllegalStateException expected) { }
}
public void testPrivateNoArgConstructorDeserialization() throws Exception {
ClassWithPrivateNoArgsConstructor target =
gson.fromJson("{\"a\":20}", ClassWithPrivateNoArgsConstructor.class);
assertEquals(20, target.a);
}
public void testAnonymousLocalClassesSerialization() throws Exception {
assertEquals("", gson.toJson(new ClassWithNoFields() {
// empty anonymous class
}));
}
public void testPrimitiveArrayFieldSerialization() {
PrimitiveArray target = new PrimitiveArray(new long[] { 1L, 2L, 3L });
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
/**
* Tests that a class field with type Object can be serialized properly.
* See issue 54
*/
public void testClassWithObjectFieldSerialization() {
ClassWithObjectField obj = new ClassWithObjectField();
obj.member = "abc";
String json = gson.toJson(obj);
assertTrue(json.contains("abc"));
}
private static class ClassWithObjectField {
Object member;
}
public void testInnerClassSerialization() {
Parent p = new Parent();
Parent.Child c = p.new Child();
String json = gson.toJson(c);
assertTrue(json.contains("value2"));
assertFalse(json.contains("value1"));
}
public void testInnerClassDeserialization() {
final Parent p = new Parent();
Gson gson = new GsonBuilder().registerTypeAdapter(
Parent.Child.class, new InstanceCreator<Parent.Child>() {
public Parent.Child createInstance(Type type) {
return p.new Child();
}
}).create();
String json = "{'value2':3}";
Parent.Child c = gson.fromJson(json, Parent.Child.class);
assertEquals(3, c.value2);
}
private static class Parent {
int value1 = 1;
private class Child {
int value2 = 2;
}
}
public static class ClassWithSubInterfacesOfCollection {
private List<Integer> list;
private Queue<Long> queue;
private Set<Float> set;
private SortedSet<Character> sortedSet;
ClassWithSubInterfacesOfCollection() {
}
public ClassWithSubInterfacesOfCollection(List<Integer> list, Queue<Long> queue, Set<Float> set,
SortedSet<Character> sortedSet) {
this.list = list;
this.queue = queue;
this.set = set;
this.sortedSet = sortedSet;
}
public String getExpectedJson() {
StringBuilder sb = new StringBuilder();
sb.append("{");
sb.append("\"list\":");
append(sb, list).append(",");
sb.append("\"queue\":");
append(sb, queue).append(",");
sb.append("\"set\":");
append(sb, set).append(",");
sb.append("\"sortedSet\":");
append(sb, sortedSet);
sb.append("}");
return sb.toString();
}
private StringBuilder append(StringBuilder sb, Collection<?> c) {
sb.append("[");
boolean first = true;
for (Object o : c) {
if (!first) {
sb.append(",");
} else {
first = false;
}
if (o instanceof String || o instanceof Character) {
sb.append('\"');
}
sb.append(o.toString());
if (o instanceof String || o instanceof Character) {
sb.append('\"');
}
}
sb.append("]");
return sb;
}
}
private static class ContainsReferenceToSelfType {
public Collection<ContainsReferenceToSelfType> children =
new ArrayList<ContainsReferenceToSelfType>();
}
private static class SubTypeOfNested extends Nested {
private final long value = 5;
public SubTypeOfNested() {
this(null, null);
}
public SubTypeOfNested(BagOfPrimitives primitive1, BagOfPrimitives primitive2) {
super(primitive1, primitive2);
}
@Override
public void appendFields(StringBuilder sb) {
sb.append("\"value\":").append(value).append(",");
super.appendFields(sb);
}
}
private static class ArrayOfArrays {
private final BagOfPrimitives[][] elements;
public ArrayOfArrays() {
elements = new BagOfPrimitives[3][2];
for (int i = 0; i < elements.length; ++i) {
BagOfPrimitives[] row = elements[i];
for (int j = 0; j < row.length; ++j) {
row[j] = new BagOfPrimitives(i+j, i*j, false, i+"_"+j);
}
}
}
public String getExpectedJson() {
StringBuilder sb = new StringBuilder("{\"elements\":[");
boolean first = true;
for (BagOfPrimitives[] row : elements) {
if (first) {
first = false;
} else {
sb.append(",");
}
boolean firstOfRow = true;
sb.append("[");
for (BagOfPrimitives element : row) {
if (firstOfRow) {
firstOfRow = false;
} else {
sb.append(",");
}
sb.append(element.getExpectedJson());
}
sb.append("]");
}
sb.append("]}");
return sb.toString();
}
}
private static class ClassWithEnumFields {
private final MyEnum value1 = MyEnum.VALUE1;
private final MyEnum value2 = MyEnum.VALUE2;
public String getExpectedJson() {
return "{\"value1\":\"" + value1 + "\",\"value2\":\"" + value2 + "\"}";
}
}
private static class ClassWithPrivateNoArgsConstructor {
public int a;
private ClassWithPrivateNoArgsConstructor() {
a = 10;
}
}
}