Removed the TypeAdapter object from GSON now that the primitive objects and fields are created by a custom Type Adapter.

This commit is contained in:
Joel Leitch 2008-11-15 05:11:28 +00:00
parent 0d8150fe52
commit cf2a457af7
11 changed files with 24 additions and 164 deletions

View File

@ -78,8 +78,6 @@ public final class Gson {
private static final String NULL_STRING = "null"; private static final String NULL_STRING = "null";
// Default instances of plug-ins // Default instances of plug-ins
static final TypeAdapter DEFAULT_TYPE_ADAPTER =
new TypeAdapterNotRequired(new PrimitiveTypeAdapter());
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY = static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC }); new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC });
static final JsonFormatter DEFAULT_JSON_FORMATTER = new JsonCompactFormatter(); static final JsonFormatter DEFAULT_JSON_FORMATTER = new JsonCompactFormatter();
@ -91,7 +89,6 @@ public final class Gson {
private final ExclusionStrategy strategy; private final ExclusionStrategy strategy;
private final FieldNamingStrategy fieldNamingPolicy; private final FieldNamingStrategy fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor; private final MappedObjectConstructor objectConstructor;
private final TypeAdapter typeAdapter;
/** Map containing Type or Class objects as keys */ /** Map containing Type or Class objects as keys */
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers; private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
@ -146,19 +143,17 @@ public final class Gson {
*/ */
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) { Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) {
this(strategy, fieldNamingPolicy, createObjectConstructor(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS), this(strategy, fieldNamingPolicy, createObjectConstructor(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS),
DEFAULT_TYPE_ADAPTER, DEFAULT_JSON_FORMATTER, false, DEFAULT_JSON_FORMATTER, false,
DefaultTypeAdapters.DEFAULT_SERIALIZERS, DefaultTypeAdapters.DEFAULT_DESERIALIZERS); DefaultTypeAdapters.DEFAULT_SERIALIZERS, DefaultTypeAdapters.DEFAULT_DESERIALIZERS);
} }
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy, Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy,
MappedObjectConstructor objectConstructor, MappedObjectConstructor objectConstructor, JsonFormatter formatter, boolean serializeNulls,
TypeAdapter typeAdapter, JsonFormatter formatter, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers, ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) { ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) {
this.strategy = strategy; this.strategy = strategy;
this.fieldNamingPolicy = fieldNamingPolicy; this.fieldNamingPolicy = fieldNamingPolicy;
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
this.typeAdapter = typeAdapter;
this.formatter = formatter; this.formatter = formatter;
this.serializeNulls = serializeNulls; this.serializeNulls = serializeNulls;
this.serializers = serializers; this.serializers = serializers;
@ -374,7 +369,7 @@ public final class Gson {
JsonParser parser = new JsonParser(json); JsonParser parser = new JsonParser(json);
JsonElement root = parser.parse(); JsonElement root = parser.parse();
JsonDeserializationContext context = new JsonDeserializationContextDefault( JsonDeserializationContext context = new JsonDeserializationContextDefault(
createDefaultObjectNavigatorFactory(), deserializers, objectConstructor, typeAdapter); createDefaultObjectNavigatorFactory(), deserializers, objectConstructor);
T target = (T) context.deserialize(root, typeOfT); T target = (T) context.deserialize(root, typeOfT);
return target; return target;
} catch (TokenMgrError e) { } catch (TokenMgrError e) {

View File

@ -55,7 +55,6 @@ public final class GsonBuilder {
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy; private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
private final InnerClassExclusionStrategy innerClassExclusionStrategy; private final InnerClassExclusionStrategy innerClassExclusionStrategy;
private boolean excludeFieldsWithoutExposeAnnotation; private boolean excludeFieldsWithoutExposeAnnotation;
private final TypeAdapter typeAdapter;
private JsonFormatter formatter; private JsonFormatter formatter;
private FieldNamingStrategy fieldNamingPolicy; private FieldNamingStrategy fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators; private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators;
@ -78,7 +77,6 @@ public final class GsonBuilder {
innerClassExclusionStrategy = new InnerClassExclusionStrategy(); innerClassExclusionStrategy = new InnerClassExclusionStrategy();
modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY; modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY;
excludeFieldsWithoutExposeAnnotation = false; excludeFieldsWithoutExposeAnnotation = false;
typeAdapter = Gson.DEFAULT_TYPE_ADAPTER;
formatter = Gson.DEFAULT_JSON_FORMATTER; formatter = Gson.DEFAULT_JSON_FORMATTER;
fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY; fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY;
instanceCreators = new ParameterizedTypeHandlerMap<InstanceCreator<?>>(); instanceCreators = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
@ -355,7 +353,7 @@ public final class GsonBuilder {
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS); customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS);
MappedObjectConstructor objConstructor = Gson.createObjectConstructor(customInstanceCreators); MappedObjectConstructor objConstructor = Gson.createObjectConstructor(customInstanceCreators);
Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor, typeAdapter, Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor,
formatter, serializeNulls, customSerializers, customDeserializers); formatter, serializeNulls, customSerializers, customDeserializers);
return gson; return gson;
} }

View File

@ -31,9 +31,9 @@ final class JsonArrayDeserializationVisitor<T> extends JsonDeserializationVisito
JsonArrayDeserializationVisitor(JsonArray jsonArray, Type arrayType, JsonArrayDeserializationVisitor(JsonArray jsonArray, Type arrayType,
ObjectNavigatorFactory factory, ObjectConstructor objectConstructor, ObjectNavigatorFactory factory, ObjectConstructor objectConstructor,
TypeAdapter typeAdapter, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) { JsonDeserializationContext context) {
super(jsonArray, arrayType, factory, objectConstructor, typeAdapter, deserializers, context); super(jsonArray, arrayType, factory, objectConstructor, deserializers, context);
} }
@Override @Override

View File

@ -28,15 +28,13 @@ final class JsonDeserializationContextDefault implements JsonDeserializationCont
private final ObjectNavigatorFactory navigatorFactory; private final ObjectNavigatorFactory navigatorFactory;
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers; private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
private final MappedObjectConstructor objectConstructor; private final MappedObjectConstructor objectConstructor;
private final TypeAdapter typeAdapter;
JsonDeserializationContextDefault(ObjectNavigatorFactory navigatorFactory, JsonDeserializationContextDefault(ObjectNavigatorFactory navigatorFactory,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
MappedObjectConstructor objectConstructor, TypeAdapter typeAdapter) { MappedObjectConstructor objectConstructor) {
this.navigatorFactory = navigatorFactory; this.navigatorFactory = navigatorFactory;
this.deserializers = deserializers; this.deserializers = deserializers;
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
this.typeAdapter = typeAdapter;
} }
ObjectConstructor getObjectConstructor() { ObjectConstructor getObjectConstructor() {
@ -61,8 +59,7 @@ final class JsonDeserializationContextDefault implements JsonDeserializationCont
private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray, private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context) throws JsonParseException {
JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>( JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>(
jsonArray, arrayType, navigatorFactory, objectConstructor, typeAdapter, deserializers, jsonArray, arrayType, navigatorFactory, objectConstructor, deserializers, context);
context);
Object target = visitor.getTarget(); Object target = visitor.getTarget();
ObjectNavigator on = navigatorFactory.create(target, arrayType); ObjectNavigator on = navigatorFactory.create(target, arrayType);
on.accept(visitor); on.accept(visitor);
@ -72,8 +69,7 @@ final class JsonDeserializationContextDefault implements JsonDeserializationCont
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject, private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>( JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
jsonObject, typeOfT, navigatorFactory, objectConstructor, typeAdapter, deserializers, jsonObject, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
context);
Object target = visitor.getTarget(); Object target = visitor.getTarget();
ObjectNavigator on = navigatorFactory.create(target, typeOfT); ObjectNavigator on = navigatorFactory.create(target, typeOfT);
on.accept(visitor); on.accept(visitor);
@ -84,13 +80,10 @@ final class JsonDeserializationContextDefault implements JsonDeserializationCont
private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json, private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json,
JsonDeserializationContext context) throws JsonParseException { JsonDeserializationContext context) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>( JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
json, typeOfT, navigatorFactory, objectConstructor, typeAdapter, deserializers, context); json, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
ObjectNavigator on = navigatorFactory.create(json.getAsObject(), typeOfT); ObjectNavigator on = navigatorFactory.create(json.getAsObject(), typeOfT);
on.accept(visitor); on.accept(visitor);
Object target = visitor.getTarget(); Object target = visitor.getTarget();
if (typeOfT instanceof Class) {
target = typeAdapter.adaptType(target, (Class) typeOfT);
}
return (T) target; return (T) target;
} }
} }

View File

@ -33,7 +33,6 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
protected final ObjectNavigatorFactory factory; protected final ObjectNavigatorFactory factory;
protected final ObjectConstructor objectConstructor; protected final ObjectConstructor objectConstructor;
protected final TypeAdapter typeAdapter;
protected final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers; protected final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
protected T target; protected T target;
protected final JsonElement json; protected final JsonElement json;
@ -41,14 +40,13 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
protected final JsonDeserializationContext context; protected final JsonDeserializationContext context;
public JsonDeserializationVisitor(JsonElement json, Type targetType, public JsonDeserializationVisitor(JsonElement json, Type targetType,
ObjectNavigatorFactory factory, ObjectConstructor objectConstructor, TypeAdapter typeAdapter, ObjectNavigatorFactory factory, ObjectConstructor objectConstructor,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) { JsonDeserializationContext context) {
Preconditions.checkNotNull(json); Preconditions.checkNotNull(json);
this.targetType = targetType; this.targetType = targetType;
this.factory = factory; this.factory = factory;
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
this.typeAdapter = typeAdapter;
this.deserializers = deserializers; this.deserializers = deserializers;
this.json = json; this.json = json;
this.context = context; this.context = context;
@ -76,14 +74,14 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
final Object visitChildAsObject(Type childType, JsonElement jsonChild) { final Object visitChildAsObject(Type childType, JsonElement jsonChild) {
JsonDeserializationVisitor<?> childVisitor = JsonDeserializationVisitor<?> childVisitor =
new JsonObjectDeserializationVisitor<Object>(jsonChild, childType, new JsonObjectDeserializationVisitor<Object>(jsonChild, childType,
factory, objectConstructor, typeAdapter, deserializers, context); factory, objectConstructor, deserializers, context);
return visitChild(childType, childVisitor); return visitChild(childType, childVisitor);
} }
final Object visitChildAsArray(Type childType, JsonArray jsonChild) { final Object visitChildAsArray(Type childType, JsonArray jsonChild) {
JsonDeserializationVisitor<?> childVisitor = JsonDeserializationVisitor<?> childVisitor =
new JsonArrayDeserializationVisitor<Object>(jsonChild.getAsJsonArray(), childType, new JsonArrayDeserializationVisitor<Object>(jsonChild.getAsJsonArray(), childType,
factory, objectConstructor, typeAdapter, deserializers, context); factory, objectConstructor, deserializers, context);
return visitChild(childType, childVisitor); return visitChild(childType, childVisitor);
} }

View File

@ -30,9 +30,9 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
JsonObjectDeserializationVisitor(JsonElement json, Type type, JsonObjectDeserializationVisitor(JsonElement json, Type type,
ObjectNavigatorFactory factory, ObjectConstructor objectConstructor, ObjectNavigatorFactory factory, ObjectConstructor objectConstructor,
TypeAdapter typeAdapter, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) { JsonDeserializationContext context) {
super(json, type, factory, objectConstructor, typeAdapter, deserializers, context); super(json, type, factory, objectConstructor, deserializers, context);
} }
@Override @Override

View File

@ -1,53 +0,0 @@
/*
* 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;
/**
* This class implements the {@link TypeAdapter} interface; however, if the
* from instance type is the same as the to type then this object will
* terminate the chain early and return the "from" object to the calling
* class.
*
* If the incoming object does need some kind of conversion then this object
* will delegate to the {@link TypeAdapter} that it is wrapping.
*
* @author Joel Leitch
*/
final class TypeAdapterNotRequired implements TypeAdapter {
private final TypeAdapter delegate;
/**
* Constructs a TypeAdapterNotRequired that will wrap the delegate instance
* that is passed in.
*
* @param delegate the TypeConverter to delegate to if this instance can
* not handle the type adapting (can not be null)
*/
TypeAdapterNotRequired(TypeAdapter delegate) {
Preconditions.checkNotNull(delegate);
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
public <T> T adaptType(Object from, Class<T> to) {
if (to.isAssignableFrom(from.getClass())) {
return (T) from;
}
return delegate.adaptType(from, to);
}
}

View File

@ -20,6 +20,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
* This class contains some test fixtures for Parameterized types. These classes should ideally * This class contains some test fixtures for Parameterized types. These classes should ideally
* belong either in the common or functional package, but they are placed here because they need * belong either in the common or functional package, but they are placed here because they need

View File

@ -20,13 +20,16 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import com.google.gson.JsonParseException;
import com.google.gson.Primitives;
/** /**
* Handles type conversion from some object to some primitive (or primitive * Handles type conversion from some object to some primitive (or primitive
* wrapper instance). * wrapper instance).
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
final class PrimitiveTypeAdapter implements TypeAdapter { final class PrimitiveTypeAdapter {
@SuppressWarnings( { "unchecked" }) @SuppressWarnings( { "unchecked" })
public <T> T adaptType(Object from, Class<T> to) { public <T> T adaptType(Object from, Class<T> to) {
@ -67,8 +70,7 @@ final class PrimitiveTypeAdapter implements TypeAdapter {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else { } else {
throw new JsonParseException( throw new JsonParseException("Can not adapt type " + from.getClass() + " to " + to);
"Can not adapt type " + from.getClass() + " to " + to);
} }
} }
} }

View File

@ -1,74 +0,0 @@
/*
* 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;
import junit.framework.TestCase;
/**
* Performs some unit testing for the {@link PrimitiveTypeAdapter} class.
*
* @author Joel Leitch
*/
public class PrimitiveTypeAdapterTest extends TestCase {
private PrimitiveTypeAdapter typeAdapter;
@Override
protected void setUp() throws Exception {
super.setUp();
typeAdapter = new PrimitiveTypeAdapter();
}
public void testImproperConversion() throws Exception {
double someValue = 1.0;
try {
typeAdapter.adaptType(someValue, String.class);
fail("Should not be able to convert incompatible types.");
} catch (JsonParseException expected) { }
}
public void testImproperCharacterConversion() throws Exception {
String someValue = "test123";
try {
typeAdapter.adaptType(someValue, Character.class);
fail("Should not be able to convert incompatible types.");
} catch (JsonParseException expected) { }
}
public void testProperPrimitiveConversions() throws Exception {
String stringValue = "1.0";
Double actualValue = typeAdapter.adaptType(stringValue, Double.class);
assertEquals(1.0, actualValue.doubleValue(), 0.0001);
Double doubleValue = 1.0;
actualValue = typeAdapter.adaptType(doubleValue, Double.class);
assertEquals(1.0, actualValue.doubleValue(), 0.0001);
stringValue = "A";
Character actualCharacter = typeAdapter.adaptType(stringValue, Character.class);
assertEquals('A', actualCharacter.charValue());
}
public void testProperEnumConversions() throws Exception {
TestEnum expected = TestEnum.TEST1;
TestEnum actual = typeAdapter.adaptType(expected, TestEnum.class);
assertEquals(expected, actual);
}
private static enum TestEnum {
TEST1, TEST2, TEST3
}
}