From 572421b7712bf2f369ec9f529416ddef5235d975 Mon Sep 17 00:00:00 2001 From: Joel Leitch Date: Fri, 20 May 2011 21:50:39 +0000 Subject: [PATCH] Open object construction in JsonDeserializationContext to leverage the same object construction as default gson deserialization. --- .../com/google/gson/BaseMapTypeAdapter.java | 8 +- .../com/google/gson/DefaultTypeAdapters.java | 7 +- gson/src/main/java/com/google/gson/Gson.java | 5 +- .../gson/JsonDeserializationContext.java | 82 +++++++++++++++-- .../JsonDeserializationContextDefault.java | 89 ------------------- .../google/gson/JsonSerializationContext.java | 40 ++++++++- .../gson/JsonSerializationContextDefault.java | 65 -------------- 7 files changed, 117 insertions(+), 179 deletions(-) delete mode 100644 gson/src/main/java/com/google/gson/JsonDeserializationContextDefault.java delete mode 100644 gson/src/main/java/com/google/gson/JsonSerializationContextDefault.java diff --git a/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java b/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java index cbe636bb..36eb40f1 100644 --- a/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java @@ -30,15 +30,11 @@ abstract class BaseMapTypeAdapter protected static final JsonElement serialize(JsonSerializationContext context, Object src, Type srcType) { - JsonSerializationContextDefault contextImpl = (JsonSerializationContextDefault) context; - return contextImpl.serialize(src, srcType, false); + return context.serialize(src, srcType, false); } - @SuppressWarnings("unchecked") protected static final Map constructMapType( Type mapType, JsonDeserializationContext context) { - JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context; - ObjectConstructor objectConstructor = contextImpl.getObjectConstructor(); - return (Map) objectConstructor.construct(mapType); + return context.construct(mapType); } } \ No newline at end of file diff --git a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java index d205bec9..9d92a816 100644 --- a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java +++ b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java @@ -677,8 +677,7 @@ final class DefaultTypeAdapters { } else { Type childType = (childGenericType == null || childGenericType == Object.class) ? child.getClass() : childGenericType; - JsonSerializationContextDefault contextImpl = (JsonSerializationContextDefault) context; - JsonElement element = contextImpl.serialize(child, childType, false); + JsonElement element = context.serialize(child, childType, false); array.add(element); } } @@ -707,9 +706,7 @@ final class DefaultTypeAdapters { private Collection constructCollectionType(Type collectionType, JsonDeserializationContext context) { - JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context; - ObjectConstructor objectConstructor = contextImpl.getObjectConstructor(); - return (Collection) objectConstructor.construct(collectionType); + return context.construct(collectionType); } } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 20517670..845dc75f 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -20,6 +20,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.google.gson.stream.MalformedJsonException; + import java.io.IOException; import java.io.Reader; import java.io.StringReader; @@ -214,7 +215,7 @@ public final class Gson { * @since 1.4 */ public JsonElement toJsonTree(Object src, Type typeOfSrc) { - JsonSerializationContextDefault context = new JsonSerializationContextDefault( + JsonSerializationContext context = new JsonSerializationContext( new ObjectNavigator(serializationExclusionStrategy), fieldNamingPolicy, serializeNulls, serializers); return context.serialize(src, typeOfSrc); @@ -545,7 +546,7 @@ public final class Gson { if (json == null) { return null; } - JsonDeserializationContext context = new JsonDeserializationContextDefault( + JsonDeserializationContext context = new JsonDeserializationContext( new ObjectNavigator(deserializationExclusionStrategy), fieldNamingPolicy, deserializers, objectConstructor); T target = (T) context.deserialize(json, typeOfT); diff --git a/gson/src/main/java/com/google/gson/JsonDeserializationContext.java b/gson/src/main/java/com/google/gson/JsonDeserializationContext.java index ae957082..c6e3cefe 100644 --- a/gson/src/main/java/com/google/gson/JsonDeserializationContext.java +++ b/gson/src/main/java/com/google/gson/JsonDeserializationContext.java @@ -19,20 +19,72 @@ package com.google.gson; import java.lang.reflect.Type; /** - * Context for deserialization that is passed to a custom deserializer during invocation of its + * Context for deserialization that is passed to a custom deserializer during invocation of its * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} - * method. - * + * method. + * * @author Inderjeet Singh * @author Joel Leitch */ -public interface JsonDeserializationContext { - +public final class JsonDeserializationContext { + private final ObjectNavigator objectNavigator; + private final FieldNamingStrategy2 fieldNamingPolicy; + private final ParameterizedTypeHandlerMap> deserializers; + private final MappedObjectConstructor objectConstructor; + + JsonDeserializationContext(ObjectNavigator objectNavigator, + FieldNamingStrategy2 fieldNamingPolicy, + ParameterizedTypeHandlerMap> deserializers, + MappedObjectConstructor objectConstructor) { + this.objectNavigator = objectNavigator; + this.fieldNamingPolicy = fieldNamingPolicy; + this.deserializers = deserializers; + this.objectConstructor = objectConstructor; + } + + + public T construct(Type type) { + return objectConstructor.construct(type); + } + + public Object constructArray(Type type, int length) { + return objectConstructor.constructArray(type, length); + } + + + private T fromJsonArray(Type arrayType, JsonArray jsonArray, + JsonDeserializationContext context) throws JsonParseException { + JsonArrayDeserializationVisitor visitor = new JsonArrayDeserializationVisitor( + jsonArray, arrayType, objectNavigator, fieldNamingPolicy, + objectConstructor, deserializers, context); + objectNavigator.accept(new ObjectTypePair(null, arrayType, true), visitor); + return visitor.getTarget(); + } + + private T fromJsonObject(Type typeOfT, JsonObject jsonObject, + JsonDeserializationContext context) throws JsonParseException { + JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor( + jsonObject, typeOfT, objectNavigator, fieldNamingPolicy, + objectConstructor, deserializers, context); + objectNavigator.accept(new ObjectTypePair(null, typeOfT, true), visitor); + return visitor.getTarget(); + } + + @SuppressWarnings("unchecked") + private T fromJsonPrimitive(Type typeOfT, JsonPrimitive json, + JsonDeserializationContext context) throws JsonParseException { + JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor( + json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context); + objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true), visitor); + Object target = visitor.getTarget(); + return (T) target; + } + /** - * Invokes default deserialization on the specified object. It should never be invoked on - * the element received as a parameter of the + * Invokes default deserialization on the specified object. It should never be invoked on + * the element received as a parameter of the * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing - * so will result in an infinite loop since Gson will in-turn call the custom deserializer again. + * so will result in an infinite loop since Gson will in-turn call the custom deserializer again. * @param json the parse tree. * @param typeOfT type of the expected return value. @@ -40,5 +92,17 @@ public interface JsonDeserializationContext { * @return An object of type typeOfT. * @throws JsonParseException if the parse tree does not contain expected data. */ - public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException; + public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException { + if (json == null || json.isJsonNull()) { + return null; + } else if (json.isJsonArray()) { + return fromJsonArray(typeOfT, json.getAsJsonArray(), this); + } else if (json.isJsonObject()) { + return fromJsonObject(typeOfT, json.getAsJsonObject(), this); + } else if (json.isJsonPrimitive()) { + return fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this); + } else { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json"); + } + } } \ No newline at end of file diff --git a/gson/src/main/java/com/google/gson/JsonDeserializationContextDefault.java b/gson/src/main/java/com/google/gson/JsonDeserializationContextDefault.java deleted file mode 100644 index 1e94ab44..00000000 --- a/gson/src/main/java/com/google/gson/JsonDeserializationContextDefault.java +++ /dev/null @@ -1,89 +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 java.lang.reflect.Type; - -/** - * implementation of a deserialization context for Gson - * - * @author Inderjeet Singh - */ -final class JsonDeserializationContextDefault implements JsonDeserializationContext { - - private final ObjectNavigator objectNavigator; - private final FieldNamingStrategy2 fieldNamingPolicy; - private final ParameterizedTypeHandlerMap> deserializers; - private final MappedObjectConstructor objectConstructor; - - JsonDeserializationContextDefault(ObjectNavigator objectNavigator, - FieldNamingStrategy2 fieldNamingPolicy, - ParameterizedTypeHandlerMap> deserializers, - MappedObjectConstructor objectConstructor) { - this.objectNavigator = objectNavigator; - this.fieldNamingPolicy = fieldNamingPolicy; - this.deserializers = deserializers; - this.objectConstructor = objectConstructor; - } - - ObjectConstructor getObjectConstructor() { - return objectConstructor; - } - - @SuppressWarnings("unchecked") - public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException { - if (json == null || json.isJsonNull()) { - return null; - } else if (json.isJsonArray()) { - return (T) fromJsonArray(typeOfT, json.getAsJsonArray(), this); - } else if (json.isJsonObject()) { - return (T) fromJsonObject(typeOfT, json.getAsJsonObject(), this); - } else if (json.isJsonPrimitive()) { - return (T) fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this); - } else { - throw new JsonParseException("Failed parsing JSON source: " + json + " to Json"); - } - } - - private T fromJsonArray(Type arrayType, JsonArray jsonArray, - JsonDeserializationContext context) throws JsonParseException { - JsonArrayDeserializationVisitor visitor = new JsonArrayDeserializationVisitor( - jsonArray, arrayType, objectNavigator, fieldNamingPolicy, - objectConstructor, deserializers, context); - objectNavigator.accept(new ObjectTypePair(null, arrayType, true), visitor); - return visitor.getTarget(); - } - - private T fromJsonObject(Type typeOfT, JsonObject jsonObject, - JsonDeserializationContext context) throws JsonParseException { - JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor( - jsonObject, typeOfT, objectNavigator, fieldNamingPolicy, - objectConstructor, deserializers, context); - objectNavigator.accept(new ObjectTypePair(null, typeOfT, true), visitor); - return visitor.getTarget(); - } - - @SuppressWarnings("unchecked") - private T fromJsonPrimitive(Type typeOfT, JsonPrimitive json, - JsonDeserializationContext context) throws JsonParseException { - JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor( - json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context); - objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true), visitor); - Object target = visitor.getTarget(); - return (T) target; - } -} diff --git a/gson/src/main/java/com/google/gson/JsonSerializationContext.java b/gson/src/main/java/com/google/gson/JsonSerializationContext.java index 5928329d..9f7515ea 100644 --- a/gson/src/main/java/com/google/gson/JsonSerializationContext.java +++ b/gson/src/main/java/com/google/gson/JsonSerializationContext.java @@ -25,7 +25,23 @@ import java.lang.reflect.Type; * @author Inderjeet Singh * @author Joel Leitch */ -public interface JsonSerializationContext { +public final class JsonSerializationContext { + + private final ObjectNavigator objectNavigator; + private final FieldNamingStrategy2 fieldNamingPolicy; + private final ParameterizedTypeHandlerMap> serializers; + private final boolean serializeNulls; + private final MemoryRefStack ancestors; + + JsonSerializationContext(ObjectNavigator objectNavigator, + FieldNamingStrategy2 fieldNamingPolicy, boolean serializeNulls, + ParameterizedTypeHandlerMap> serializers) { + this.objectNavigator = objectNavigator; + this.fieldNamingPolicy = fieldNamingPolicy; + this.serializeNulls = serializeNulls; + this.serializers = serializers; + this.ancestors = new MemoryRefStack(); + } /** * Invokes default serialization on the specified object. @@ -33,7 +49,12 @@ public interface JsonSerializationContext { * @param src the object that needs to be serialized. * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}. */ - public JsonElement serialize(Object src); + public JsonElement serialize(Object src) { + if (src == null) { + return JsonNull.createJsonNull(); + } + return serialize(src, src.getClass(), false); + } /** * Invokes default serialization on the specified object passing the specific type information. @@ -45,5 +66,18 @@ public interface JsonSerializationContext { * @param typeOfSrc the actual genericized type of src object. * @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); + } + + JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType) { + if (src == null) { + return JsonNull.createJsonNull(); + } + JsonSerializationVisitor visitor = new JsonSerializationVisitor( + objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors); + ObjectTypePair objTypePair = new ObjectTypePair(src, typeOfSrc, preserveType); + objectNavigator.accept(objTypePair, visitor); + return visitor.getJsonElement(); + } } \ No newline at end of file diff --git a/gson/src/main/java/com/google/gson/JsonSerializationContextDefault.java b/gson/src/main/java/com/google/gson/JsonSerializationContextDefault.java deleted file mode 100644 index c7abbe6a..00000000 --- a/gson/src/main/java/com/google/gson/JsonSerializationContextDefault.java +++ /dev/null @@ -1,65 +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 java.lang.reflect.Type; - -/** - * An implementation of serialization context for Gson. - * - * @author Inderjeet Singh - */ -final class JsonSerializationContextDefault implements JsonSerializationContext { - - private final ObjectNavigator objectNavigator; - private final FieldNamingStrategy2 fieldNamingPolicy; - private final ParameterizedTypeHandlerMap> serializers; - private final boolean serializeNulls; - private final MemoryRefStack ancestors; - - JsonSerializationContextDefault(ObjectNavigator objectNavigator, - FieldNamingStrategy2 fieldNamingPolicy, boolean serializeNulls, - ParameterizedTypeHandlerMap> serializers) { - this.objectNavigator = objectNavigator; - this.fieldNamingPolicy = fieldNamingPolicy; - this.serializeNulls = serializeNulls; - this.serializers = serializers; - this.ancestors = new MemoryRefStack(); - } - - public JsonElement serialize(Object src) { - if (src == null) { - return JsonNull.createJsonNull(); - } - return serialize(src, src.getClass(), false); - } - - public JsonElement serialize(Object src, Type typeOfSrc) { - return serialize(src, typeOfSrc, true); - } - - JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType) { - if (src == null) { - return JsonNull.createJsonNull(); - } - JsonSerializationVisitor visitor = new JsonSerializationVisitor( - objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors); - ObjectTypePair objTypePair = new ObjectTypePair(src, typeOfSrc, preserveType); - objectNavigator.accept(objTypePair, visitor); - return visitor.getJsonElement(); - } -} \ No newline at end of file