bb7f0b6bb0
Add setSerializeNulls() to JsonWriter, so nulls can be skipped from serialization. This does not yet impact JsonElementWriter. One change in behavior: if the only value is skipped, we now emit "null" rather than "".
462 lines
16 KiB
Java
462 lines
16 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.JsonObject;
|
|
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.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.Nested;
|
|
import com.google.gson.common.TestTypes.PrimitiveArray;
|
|
|
|
import com.google.gson.reflect.TypeToken;
|
|
import java.util.List;
|
|
import junit.framework.TestCase;
|
|
|
|
import java.lang.reflect.Type;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
|
|
/**
|
|
* 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 testClassWithTransientFieldsSerialization() throws Exception {
|
|
ClassWithTransientFields<Long> target = new ClassWithTransientFields<Long>(1L);
|
|
assertEquals(target.getExpectedJson(), gson.toJson(target));
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public void testClassWithTransientFieldsDeserialization() throws Exception {
|
|
String json = "{\"longValue\":[1]}";
|
|
ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class);
|
|
assertEquals(json, target.getExpectedJson());
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
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 testNullSerialization() throws Exception {
|
|
assertEquals("", gson.toJson(null));
|
|
}
|
|
|
|
public void testEmptyStringDeserialization() throws Exception {
|
|
Object object = gson.fromJson("", Object.class);
|
|
assertNull(object);
|
|
}
|
|
|
|
public void testTruncatedDeserialization() {
|
|
try {
|
|
gson.fromJson("[\"a\", \"b\",", new TypeToken<List<String>>() {}.getType());
|
|
fail();
|
|
} catch (JsonParseException expected) {
|
|
}
|
|
}
|
|
|
|
public void testNullDeserialization() throws Exception {
|
|
String myNullObject = null;
|
|
Object object = gson.fromJson(myNullObject, Object.class);
|
|
assertNull(object);
|
|
}
|
|
|
|
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 testArrayOfObjectsAsFields() throws Exception {
|
|
ClassWithObjects classWithObjects = new ClassWithObjects();
|
|
BagOfPrimitives bagOfPrimitives = new BagOfPrimitives();
|
|
String stringValue = "someStringValueInArray";
|
|
String classWithObjectsJson = gson.toJson(classWithObjects);
|
|
String bagOfPrimitivesJson = gson.toJson(bagOfPrimitives);
|
|
|
|
ClassWithArray classWithArray = new ClassWithArray(
|
|
new Object[] { stringValue, classWithObjects, bagOfPrimitives });
|
|
String json = gson.toJson(classWithArray);
|
|
|
|
assertTrue(json.contains(classWithObjectsJson));
|
|
assertTrue(json.contains(bagOfPrimitivesJson));
|
|
assertTrue(json.contains("\"" + stringValue + "\""));
|
|
}
|
|
|
|
/**
|
|
* 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\":[]}";
|
|
ClassWithCollectionField target = gson.fromJson(json, ClassWithCollectionField.class);
|
|
assertNotNull(target);
|
|
assertTrue(target.children.isEmpty());
|
|
}
|
|
|
|
private static class ClassWithCollectionField {
|
|
Collection<String> children = new ArrayList<String>();
|
|
}
|
|
|
|
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 {
|
|
ClassWithCollectionField target = new ClassWithCollectionField();
|
|
assertEquals("{\"children\":[]}", gson.toJson(target));
|
|
}
|
|
|
|
public void testPrivateNoArgConstructorDeserialization() throws Exception {
|
|
ClassWithPrivateNoArgsConstructor target =
|
|
gson.fromJson("{\"a\":20}", ClassWithPrivateNoArgsConstructor.class);
|
|
assertEquals(20, target.a);
|
|
}
|
|
|
|
public void testAnonymousLocalClassesSerialization() throws Exception {
|
|
assertEquals("null", 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 {
|
|
@SuppressWarnings("unused")
|
|
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 {
|
|
@SuppressWarnings("unused")
|
|
int value1 = 1;
|
|
private class Child {
|
|
int value2 = 2;
|
|
}
|
|
}
|
|
|
|
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 ClassWithPrivateNoArgsConstructor {
|
|
public int a;
|
|
private ClassWithPrivateNoArgsConstructor() {
|
|
a = 10;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* In response to Issue 41 http://code.google.com/p/google-gson/issues/detail?id=41
|
|
*/
|
|
public void testObjectFieldNamesWithoutQuotesDeserialization() {
|
|
String json = "{longValue:1,'booleanValue':true,\"stringValue\":'bar'}";
|
|
BagOfPrimitives bag = gson.fromJson(json, BagOfPrimitives.class);
|
|
assertEquals(1, bag.longValue);
|
|
assertTrue(bag.booleanValue);
|
|
assertEquals("bar", bag.stringValue);
|
|
}
|
|
|
|
public void testStringFieldWithNumberValueDeserialization() {
|
|
String json = "{\"stringValue\":1}";
|
|
BagOfPrimitives bag = gson.fromJson(json, BagOfPrimitives.class);
|
|
assertEquals("1", bag.stringValue);
|
|
|
|
json = "{\"stringValue\":1.5E+6}";
|
|
bag = gson.fromJson(json, BagOfPrimitives.class);
|
|
assertEquals("1.5E+6", bag.stringValue);
|
|
|
|
json = "{\"stringValue\":true}";
|
|
bag = gson.fromJson(json, BagOfPrimitives.class);
|
|
assertEquals("true", bag.stringValue);
|
|
}
|
|
|
|
/**
|
|
* Created to reproduce issue 140
|
|
*/
|
|
public void testStringFieldWithEmptyValueSerialization() {
|
|
ClassWithEmptyStringFields target = new ClassWithEmptyStringFields();
|
|
target.a = "5794749";
|
|
String json = gson.toJson(target);
|
|
assertTrue(json.contains("\"a\":\"5794749\""));
|
|
assertTrue(json.contains("\"b\":\"\""));
|
|
assertTrue(json.contains("\"c\":\"\""));
|
|
}
|
|
|
|
/**
|
|
* Created to reproduce issue 140
|
|
*/
|
|
public void testStringFieldWithEmptyValueDeserialization() {
|
|
String json = "{a:\"5794749\",b:\"\",c:\"\"}";
|
|
ClassWithEmptyStringFields target = gson.fromJson(json, ClassWithEmptyStringFields.class);
|
|
assertEquals("5794749", target.a);
|
|
assertEquals("", target.b);
|
|
assertEquals("", target.c);
|
|
}
|
|
|
|
private static class ClassWithEmptyStringFields {
|
|
String a = "";
|
|
String b = "";
|
|
String c = "";
|
|
}
|
|
|
|
public void testJsonObjectSerialization() {
|
|
Gson gson = new GsonBuilder().serializeNulls().create();
|
|
JsonObject obj = new JsonObject();
|
|
String json = gson.toJson(obj);
|
|
assertEquals("{}", json);
|
|
}
|
|
|
|
/**
|
|
* Test for issue 215.
|
|
*/
|
|
public void testSingletonLists() {
|
|
Gson gson = new Gson();
|
|
Product product = new Product();
|
|
assertEquals("{\"attributes\":[],\"departments\":[]}",
|
|
gson.toJson(product));
|
|
gson.fromJson(gson.toJson(product), Product.class);
|
|
|
|
product.departments.add(new Department());
|
|
assertEquals("{\"attributes\":[],\"departments\":[{\"name\":\"abc\",\"code\":\"123\"}]}",
|
|
gson.toJson(product));
|
|
gson.fromJson(gson.toJson(product), Product.class);
|
|
|
|
product.attributes.add("456");
|
|
assertEquals("{\"attributes\":[\"456\"],\"departments\":[{\"name\":\"abc\",\"code\":\"123\"}]}",
|
|
gson.toJson(product));
|
|
gson.fromJson(gson.toJson(product), Product.class);
|
|
}
|
|
|
|
static final class Department {
|
|
public String name = "abc";
|
|
public String code = "123";
|
|
}
|
|
|
|
static final class Product {
|
|
private List<String> attributes = new ArrayList<String>();
|
|
private List<Department> departments = new ArrayList<Department>();
|
|
}
|
|
|
|
}
|