Added serializeDefault and deserializeDefault methods in contexts that only invoke system type adapters on the top-level object.

With this, the RuntimeTypeAdapterTest passes.
This commit is contained in:
Inderjeet Singh 2011-07-01 21:29:20 +00:00
parent 5f4e88f62a
commit 62675b7f46
15 changed files with 170 additions and 60 deletions

View File

@ -184,7 +184,7 @@ public final class RuntimeTypeAdapter<T> implements JsonSerializer<T>, JsonDeser
throw new JsonParseException("cannot serialize " + srcType.getName() throw new JsonParseException("cannot serialize " + srcType.getName()
+ "; did you forget to register a subtype?"); + "; did you forget to register a subtype?");
} }
JsonElement serialized = context.serialize(src, srcType); JsonElement serialized = context.serializeDefault(src, srcType);
final JsonObject jsonObject = serialized.getAsJsonObject(); final JsonObject jsonObject = serialized.getAsJsonObject();
if (jsonObject.has(typeFieldName)) { if (jsonObject.has(typeFieldName)) {
throw new JsonParseException("cannot serialize " + srcType.getName() throw new JsonParseException("cannot serialize " + srcType.getName()
@ -212,7 +212,7 @@ public final class RuntimeTypeAdapter<T> implements JsonSerializer<T>, JsonDeser
+ label + "; did you forget to register a subtype?"); + label + "; did you forget to register a subtype?");
} }
@SuppressWarnings("unchecked") // registration requires that subtype extends T @SuppressWarnings("unchecked") // registration requires that subtype extends T
T result = (T) context.deserialize(json, subtype); T result = (T) context.deserializeDefault(json, subtype);
return result; return result;
} }
} }

View File

@ -50,7 +50,7 @@ public final class RuntimeTypeAdapterTest extends TestCase {
assertEquals("{\"type\":\"BillingInstrument\",\"ownerName\":\"Jesse\"}", assertEquals("{\"type\":\"BillingInstrument\",\"ownerName\":\"Jesse\"}",
gson.toJson(original, BillingInstrument.class)); gson.toJson(original, BillingInstrument.class));
BillingInstrument deserialized = gson.fromJson( BillingInstrument deserialized = gson.fromJson(
"{type:'CreditCard',ownerName:'Jesse'}", BillingInstrument.class); "{type:'BillingInstrument',ownerName:'Jesse'}", BillingInstrument.class);
assertEquals("Jesse", deserialized.ownerName); assertEquals("Jesse", deserialized.ownerName);
} }

View File

@ -30,7 +30,7 @@ abstract class BaseMapTypeAdapter
protected static final JsonElement serialize(JsonSerializationContext context, protected static final JsonElement serialize(JsonSerializationContext context,
Object src, Type srcType) { Object src, Type srcType) {
return context.serialize(src, srcType, false); return context.serialize(src, srcType, false, false);
} }
protected static final Map<Object, Object> constructMapType( protected static final Map<Object, Object> constructMapType(

View File

@ -677,7 +677,7 @@ final class DefaultTypeAdapters {
} else { } else {
Type childType = (childGenericType == null || childGenericType == Object.class) Type childType = (childGenericType == null || childGenericType == Object.class)
? child.getClass() : childGenericType; ? child.getClass() : childGenericType;
JsonElement element = context.serialize(child, childType, false); JsonElement element = context.serialize(child, childType, false, false);
array.add(element); array.add(element);
} }
} }

View File

@ -55,29 +55,29 @@ public final class JsonDeserializationContext {
private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray, private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>( JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>(
jsonArray, arrayType, objectNavigator, fieldNamingPolicy, jsonArray, arrayType, objectNavigator, fieldNamingPolicy,
objectConstructor, deserializers, context); objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(null, arrayType, true), visitor); objectNavigator.accept(new ObjectTypePair(null, arrayType, true, systemOnly), visitor);
return visitor.getTarget(); return visitor.getTarget();
} }
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject, private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>( JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
jsonObject, typeOfT, objectNavigator, fieldNamingPolicy, jsonObject, typeOfT, objectNavigator, fieldNamingPolicy,
objectConstructor, deserializers, context); objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(null, typeOfT, true), visitor); objectNavigator.accept(new ObjectTypePair(null, typeOfT, true, systemOnly), visitor);
return visitor.getTarget(); return visitor.getTarget();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json, private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>( JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context); json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true), visitor); objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true, systemOnly), visitor);
Object target = visitor.getTarget(); Object target = visitor.getTarget();
return (T) target; return (T) target;
} }
@ -99,13 +99,31 @@ public final class JsonDeserializationContext {
if (json == null || json.isJsonNull()) { if (json == null || json.isJsonNull()) {
return null; return null;
} else if (json.isJsonArray()) { } else if (json.isJsonArray()) {
Object array = fromJsonArray(typeOfT, json.getAsJsonArray(), this); Object array = fromJsonArray(typeOfT, json.getAsJsonArray(), this, false);
return (T) array; return (T) array;
} else if (json.isJsonObject()) { } else if (json.isJsonObject()) {
Object object = fromJsonObject(typeOfT, json.getAsJsonObject(), this); Object object = fromJsonObject(typeOfT, json.getAsJsonObject(), this, false);
return (T) object; return (T) object;
} else if (json.isJsonPrimitive()) { } else if (json.isJsonPrimitive()) {
Object primitive = fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this); Object primitive = fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this, false);
return (T) primitive;
} else {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");
}
}
@SuppressWarnings("unchecked")
public <T> T deserializeDefault(JsonElement json, Type typeOfT) throws JsonParseException {
if (json == null || json.isJsonNull()) {
return null;
} else if (json.isJsonArray()) {
Object array = fromJsonArray(typeOfT, json.getAsJsonArray(), this, true);
return (T) array;
} else if (json.isJsonObject()) {
Object object = fromJsonObject(typeOfT, json.getAsJsonObject(), this, true);
return (T) object;
} else if (json.isJsonPrimitive()) {
Object primitive = fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this, true);
return (T) primitive; return (T) primitive;
} else { } else {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json"); throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");

View File

@ -107,7 +107,7 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
} }
private Object visitChild(Type type, JsonDeserializationVisitor<?> childVisitor) { private Object visitChild(Type type, JsonDeserializationVisitor<?> childVisitor) {
objectNavigator.accept(new ObjectTypePair(null, type, false), childVisitor); objectNavigator.accept(new ObjectTypePair(null, type, false, false), childVisitor);
// the underlying object may have changed during the construction phase // the underlying object may have changed during the construction phase
// This happens primarily because of custom deserializers // This happens primarily because of custom deserializers
return childVisitor.getTarget(); return childVisitor.getTarget();

View File

@ -109,7 +109,7 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
} }
return true; return true;
} }
ObjectTypePair objTypePair = new ObjectTypePair(null, declaredTypeOfField, false); ObjectTypePair objTypePair = new ObjectTypePair(null, declaredTypeOfField, false, false);
Pair<JsonDeserializer<?>, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers); Pair<JsonDeserializer<?>, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
if (pair == null) { if (pair == null) {
return false; return false;

View File

@ -53,7 +53,7 @@ public final class JsonSerializationContext {
if (src == null) { if (src == null) {
return JsonNull.INSTANCE; return JsonNull.INSTANCE;
} }
return serialize(src, src.getClass(), false); return serialize(src, src.getClass(), false, false);
} }
/** /**
@ -67,16 +67,20 @@ public final class JsonSerializationContext {
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}. * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/ */
public JsonElement serialize(Object src, Type typeOfSrc) { public JsonElement serialize(Object src, Type typeOfSrc) {
return serialize(src, typeOfSrc, true); return serialize(src, typeOfSrc, true, false);
} }
JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType) { public JsonElement serializeDefault(Object src, Type typeOfSrc) {
return serialize(src, typeOfSrc, true, true);
}
JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType, boolean defaultOnly) {
if (src == null) { if (src == null) {
return JsonNull.INSTANCE; return JsonNull.INSTANCE;
} }
JsonSerializationVisitor visitor = new JsonSerializationVisitor( JsonSerializationVisitor visitor = new JsonSerializationVisitor(
objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors); objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors);
ObjectTypePair objTypePair = new ObjectTypePair(src, typeOfSrc, preserveType); ObjectTypePair objTypePair = new ObjectTypePair(src, typeOfSrc, preserveType, defaultOnly);
objectNavigator.accept(objTypePair, visitor); objectNavigator.accept(objTypePair, visitor);
return visitor.getJsonElement(); return visitor.getJsonElement();
} }

View File

@ -54,7 +54,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
} }
public void start(ObjectTypePair node) { public void start(ObjectTypePair node) {
if (node == null) { if (node == null || node.isSystemOnly()) {
return; return;
} }
if (ancestors.contains(node)) { if (ancestors.contains(node)) {
@ -64,7 +64,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
} }
public void end(ObjectTypePair node) { public void end(ObjectTypePair node) {
if (node != null) { if (node != null && !node.isSystemOnly()) {
ancestors.pop(); ancestors.pop();
} }
} }
@ -81,7 +81,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
Object child = Array.get(array, i); Object child = Array.get(array, i);
// we should not get more specific component type yet since it is possible // we should not get more specific component type yet since it is possible
// that a custom serializer is registered for the componentType // that a custom serializer is registered for the componentType
addAsArrayElement(new ObjectTypePair(child, componentType, false)); addAsArrayElement(new ObjectTypePair(child, componentType, false, false));
} }
} }
@ -93,7 +93,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
} }
} else { } else {
Object array = getFieldValue(f, obj); Object array = getFieldValue(f, obj);
addAsChildOfObject(f, new ObjectTypePair(array, typeOfF, false)); addAsChildOfObject(f, new ObjectTypePair(array, typeOfF, false, false));
} }
} catch (CircularReferenceException e) { } catch (CircularReferenceException e) {
throw e.createDetailedException(f); throw e.createDetailedException(f);
@ -111,7 +111,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
// we should not get more specific component type yet since it is // we should not get more specific component type yet since it is
// possible that a custom // possible that a custom
// serializer is registered for the componentType // serializer is registered for the componentType
addAsChildOfObject(f, new ObjectTypePair(fieldValue, typeOfF, false)); addAsChildOfObject(f, new ObjectTypePair(fieldValue, typeOfF, false, false));
} }
} catch (CircularReferenceException e) { } catch (CircularReferenceException e) {
throw e.createDetailedException(f); throw e.createDetailedException(f);
@ -200,7 +200,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
} }
return true; return true;
} }
ObjectTypePair objTypePair = new ObjectTypePair(obj, declaredTypeOfField, false); ObjectTypePair objTypePair = new ObjectTypePair(obj, declaredTypeOfField, false, false);
JsonElement child = findAndInvokeCustomSerializer(objTypePair); JsonElement child = findAndInvokeCustomSerializer(objTypePair);
if (child != null) { if (child != null) {
addChildAsElement(f, child); addChildAsElement(f, child);

View File

@ -45,7 +45,7 @@ final class MappedObjectConstructor implements ObjectConstructor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T construct(Type typeOfT) { public <T> T construct(Type typeOfT) {
InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreatorMap.getHandlerFor(typeOfT); InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreatorMap.getHandlerFor(typeOfT, false);
if (creator != null) { if (creator != null) {
return creator.createInstance(typeOfT); return creator.createInstance(typeOfT);
} }

View File

@ -27,11 +27,13 @@ final class ObjectTypePair {
private Object obj; private Object obj;
final Type type; final Type type;
private final boolean preserveType; private final boolean preserveType;
private final boolean systemOnly;
ObjectTypePair(Object obj, Type type, boolean preserveType) { ObjectTypePair(Object obj, Type type, boolean preserveType, boolean systemOnly) {
this.obj = obj; this.obj = obj;
this.type = type; this.type = type;
this.preserveType = preserveType; this.preserveType = preserveType;
this.systemOnly = systemOnly;
} }
Object getObject() { Object getObject() {
@ -57,13 +59,13 @@ final class ObjectTypePair {
if (!preserveType && obj != null) { if (!preserveType && obj != null) {
// First try looking up the handler for the actual type // First try looking up the handler for the actual type
ObjectTypePair moreSpecificType = toMoreSpecificType(); ObjectTypePair moreSpecificType = toMoreSpecificType();
handler = handlers.getHandlerFor(moreSpecificType.type); handler = handlers.getHandlerFor(moreSpecificType.type, systemOnly);
if (handler != null) { if (handler != null) {
return new Pair<HANDLER, ObjectTypePair>(handler, moreSpecificType); return new Pair<HANDLER, ObjectTypePair>(handler, moreSpecificType);
} }
} }
// Try the specified type // Try the specified type
handler = handlers.getHandlerFor(type); handler = handlers.getHandlerFor(type, systemOnly);
return handler == null ? null : new Pair<HANDLER, ObjectTypePair>(handler, this); return handler == null ? null : new Pair<HANDLER, ObjectTypePair>(handler, this);
} }
@ -75,7 +77,7 @@ final class ObjectTypePair {
if (actualType == type) { if (actualType == type) {
return this; return this;
} }
return new ObjectTypePair(obj, actualType, true); return new ObjectTypePair(obj, actualType, true, systemOnly);
} }
Type getMoreSpecificType() { Type getMoreSpecificType() {
@ -135,10 +137,14 @@ final class ObjectTypePair {
} else if (!type.equals(other.type)) { } else if (!type.equals(other.type)) {
return false; return false;
} }
return preserveType == other.preserveType; return preserveType == other.preserveType && systemOnly == other.systemOnly;
} }
public boolean isPreserveType() { public boolean isPreserveType() {
return preserveType; return preserveType;
} }
public boolean isSystemOnly() {
return systemOnly;
}
} }

View File

@ -164,10 +164,13 @@ final class ParameterizedTypeHandlerMap<T> {
modifiable = false; modifiable = false;
} }
public synchronized T getHandlerFor(Type type) { public synchronized T getHandlerFor(Type type, boolean systemOnly) {
T handler = userMap.get(type); T handler;
if (handler != null) { if (!systemOnly) {
return handler; handler = userMap.get(type);
if (handler != null) {
return handler;
}
} }
handler = systemMap.get(type); handler = systemMap.get(type);
if (handler != null) { if (handler != null) {
@ -175,20 +178,22 @@ final class ParameterizedTypeHandlerMap<T> {
} }
Class<?> rawClass = $Gson$Types.getRawType(type); Class<?> rawClass = $Gson$Types.getRawType(type);
if (rawClass != type) { if (rawClass != type) {
handler = getHandlerFor(rawClass); handler = getHandlerFor(rawClass, systemOnly);
if (handler != null) { if (handler != null) {
return handler; return handler;
} }
} }
// check if something registered for type hierarchy // check if something registered for type hierarchy
handler = getHandlerForTypeHierarchy(rawClass); handler = getHandlerForTypeHierarchy(rawClass, systemOnly);
return handler; return handler;
} }
private T getHandlerForTypeHierarchy(Class<?> type) { private T getHandlerForTypeHierarchy(Class<?> type, boolean systemOnly) {
for (Pair<Class<?>, T> entry : userTypeHierarchyList) { if (!systemOnly) {
if (entry.first.isAssignableFrom(type)) { for (Pair<Class<?>, T> entry : userTypeHierarchyList) {
return entry.second; if (entry.first.isAssignableFrom(type)) {
return entry.second;
}
} }
} }
for (Pair<Class<?>, T> entry : systemTypeHierarchyList) { for (Pair<Class<?>, T> entry : systemTypeHierarchyList) {

View File

@ -42,7 +42,7 @@ public class MemoryRefStackTest extends TestCase {
} }
public void testPushPeekAndPop() throws Exception { public void testPushPeekAndPop() throws Exception {
ObjectTypePair obj = new ObjectTypePair(this, getClass(), true); ObjectTypePair obj = new ObjectTypePair(this, getClass(), true, false);
assertEquals(obj, stack.push(obj)); assertEquals(obj, stack.push(obj));
assertEquals(obj, stack.peek()); assertEquals(obj, stack.peek());
@ -50,7 +50,7 @@ public class MemoryRefStackTest extends TestCase {
} }
public void testPopTooMany() throws Exception { public void testPopTooMany() throws Exception {
ObjectTypePair obj = new ObjectTypePair(this, getClass(), true); ObjectTypePair obj = new ObjectTypePair(this, getClass(), true, false);
stack.push(obj); stack.push(obj);
assertEquals(obj, stack.pop()); assertEquals(obj, stack.pop());
@ -63,9 +63,9 @@ public class MemoryRefStackTest extends TestCase {
MockObject objA = new MockObject(); MockObject objA = new MockObject();
MockObject objB = new MockObject(); MockObject objB = new MockObject();
assertEquals(objA, objB); assertEquals(objA, objB);
stack.push(new ObjectTypePair(objA, MockObject.class, true)); stack.push(new ObjectTypePair(objA, MockObject.class, true, false));
assertTrue(stack.contains(new ObjectTypePair(objA, MockObject.class, true))); assertTrue(stack.contains(new ObjectTypePair(objA, MockObject.class, true, false)));
assertFalse(stack.contains(new ObjectTypePair(objB, MockObject.class, true))); assertFalse(stack.contains(new ObjectTypePair(objB, MockObject.class, true, false)));
} }
private static class MockObject { private static class MockObject {

View File

@ -41,8 +41,8 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testNullMap() throws Exception { public void testNullMap() throws Exception {
assertFalse(paramMap.hasSpecificHandlerFor(String.class)); assertFalse(paramMap.hasSpecificHandlerFor(String.class));
assertNull(paramMap.getHandlerFor(String.class)); assertNull(paramMap.getHandlerFor(String.class, false));
assertNull(paramMap.getHandlerFor(String.class)); assertNull(paramMap.getHandlerFor(String.class, false));
} }
public void testHasGenericButNotSpecific() throws Exception { public void testHasGenericButNotSpecific() throws Exception {
@ -52,9 +52,9 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
assertFalse(paramMap.hasSpecificHandlerFor(specificType)); assertFalse(paramMap.hasSpecificHandlerFor(specificType));
assertTrue(paramMap.hasSpecificHandlerFor(List.class)); assertTrue(paramMap.hasSpecificHandlerFor(List.class));
assertNotNull(paramMap.getHandlerFor(specificType)); assertNotNull(paramMap.getHandlerFor(specificType, false));
assertNotNull(paramMap.getHandlerFor(List.class)); assertNotNull(paramMap.getHandlerFor(List.class, false));
assertEquals(handler, paramMap.getHandlerFor(specificType)); assertEquals(handler, paramMap.getHandlerFor(specificType, false));
} }
public void testHasSpecificType() throws Exception { public void testHasSpecificType() throws Exception {
@ -64,9 +64,9 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
assertTrue(paramMap.hasSpecificHandlerFor(specificType)); assertTrue(paramMap.hasSpecificHandlerFor(specificType));
assertFalse(paramMap.hasSpecificHandlerFor(List.class)); assertFalse(paramMap.hasSpecificHandlerFor(List.class));
assertNotNull(paramMap.getHandlerFor(specificType)); assertNotNull(paramMap.getHandlerFor(specificType, false));
assertNull(paramMap.getHandlerFor(List.class)); assertNull(paramMap.getHandlerFor(List.class, false));
assertEquals(handler, paramMap.getHandlerFor(specificType)); assertEquals(handler, paramMap.getHandlerFor(specificType, false));
} }
public void testTypeOverridding() throws Exception { public void testTypeOverridding() throws Exception {
@ -76,7 +76,7 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
paramMap.register(String.class, handler2, false); paramMap.register(String.class, handler2, false);
assertTrue(paramMap.hasSpecificHandlerFor(String.class)); assertTrue(paramMap.hasSpecificHandlerFor(String.class));
assertEquals(handler2, paramMap.getHandlerFor(String.class)); assertEquals(handler2, paramMap.getHandlerFor(String.class, false));
} }
public void testMakeUnmodifiable() throws Exception { public void testMakeUnmodifiable() throws Exception {
@ -89,14 +89,14 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testTypeHierarchy() { public void testTypeHierarchy() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false);
String handler = paramMap.getHandlerFor(Sub.class); String handler = paramMap.getHandlerFor(Sub.class, false);
assertEquals("baseHandler", handler); assertEquals("baseHandler", handler);
} }
public void testTypeHierarchyMultipleHandlers() { public void testTypeHierarchyMultipleHandlers() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false);
paramMap.registerForTypeHierarchy(Sub.class, "subHandler", false); paramMap.registerForTypeHierarchy(Sub.class, "subHandler", false);
String handler = paramMap.getHandlerFor(SubOfSub.class); String handler = paramMap.getHandlerFor(SubOfSub.class, false);
assertEquals("subHandler", handler); assertEquals("subHandler", handler);
} }
@ -105,14 +105,14 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
ParameterizedTypeHandlerMap<String> otherMap = new ParameterizedTypeHandlerMap<String>(); ParameterizedTypeHandlerMap<String> otherMap = new ParameterizedTypeHandlerMap<String>();
otherMap.registerForTypeHierarchy(Base.class, "baseHandler2", false); otherMap.registerForTypeHierarchy(Base.class, "baseHandler2", false);
paramMap.registerIfAbsent(otherMap); paramMap.registerIfAbsent(otherMap);
String handler = paramMap.getHandlerFor(Base.class); String handler = paramMap.getHandlerFor(Base.class, false);
assertEquals("baseHandler", handler); assertEquals("baseHandler", handler);
} }
public void testReplaceExistingTypeHierarchyHandler() { public void testReplaceExistingTypeHierarchyHandler() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false);
paramMap.registerForTypeHierarchy(Base.class, "base2Handler", false); paramMap.registerForTypeHierarchy(Base.class, "base2Handler", false);
String handler = paramMap.getHandlerFor(Base.class); String handler = paramMap.getHandlerFor(Base.class, false);
assertEquals("base2Handler", handler); assertEquals("base2Handler", handler);
} }

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2011 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 java.lang.reflect.Type;
import junit.framework.TestCase;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
/**
* Functional tests for serialize default behavior where a custom type adapter is allowed to invoke
* context.serialize on self.
*
* @author Inderjeet Singh
*/
public class SystemOnlyTypeAdaptersTest extends TestCase {
private Gson gson;
@Override
protected void setUp() throws Exception {
super.setUp();
this.gson = new GsonBuilder().registerTypeAdapter(Foo.class, new FooTypeAdapter()).create();
}
public void testSerializeDefault() {
String json = gson.toJson(new Foo());
assertEquals("{\"a\":10,\"secret-key\":\"abracadabra\"}", json);
}
public void testDeserializeDefault() {
String json = "{a:5,'secret-key':'abracadabra'}";
Foo foo = gson.fromJson(json, Foo.class);
assertEquals(5, foo.a);
}
private static class Foo {
int a = 10;
}
private static class FooTypeAdapter implements JsonSerializer<Foo>, JsonDeserializer<Foo> {
public JsonElement serialize(Foo src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject json = context.serializeDefault(src, typeOfSrc).getAsJsonObject();
json.addProperty("secret-key", "abracadabra");
return json;
}
public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!"abracadabra".equals(json.getAsJsonObject().get("secret-key").getAsString())) {
throw new IllegalArgumentException("invalid key");
}
return context.deserializeDefault(json, typeOfT);
}
}
}