diff --git a/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java b/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java
deleted file mode 100644
index b196e7cc..00000000
--- a/gson/src/main/java/com/google/gson/BaseMapTypeAdapter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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;
-
-import java.lang.reflect.Type;
-import java.util.Map;
-
-/**
- * Captures all the common/shared logic between the old, ({@link MapTypeAdapter}, and
- * the new, {@link MapAsArrayTypeAdapter}, map type adapters.
- *
- * @author Joel Leitch
- */
-abstract class BaseMapTypeAdapter
- implements JsonSerializer>, JsonDeserializer> {
-
- protected static JsonElement serialize(JsonSerializationContext context,
- Object src, Type srcType) {
- return context.serialize(src, srcType, false, false);
- }
-
- protected static Map constructMapType(
- Type mapType, JsonDeserializationContext context) {
- 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 2870775f..c201178e 100644
--- a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java
+++ b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java
@@ -16,30 +16,19 @@
package com.google.gson;
-import com.google.gson.internal.$Gson$Types;
+import com.google.gson.internal.ParameterizedTypeHandlerMap;
import java.lang.reflect.Type;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
-import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
import java.util.TimeZone;
-import java.util.TreeSet;
/**
* List of all the default type adapters ({@link JsonSerializer}s, {@link JsonDeserializer}s,
@@ -61,7 +50,6 @@ final class DefaultTypeAdapters {
@SuppressWarnings("unchecked")
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
private static final BitSetTypeAdapter BIT_SET_ADAPTER = new BitSetTypeAdapter();
- private static final MapTypeAdapter MAP_TYPE_ADAPTER = new MapTypeAdapter();
private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter();
private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
@@ -107,7 +95,6 @@ final class DefaultTypeAdapters {
ParameterizedTypeHandlerMap> map =
new ParameterizedTypeHandlerMap>();
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER, true);
- map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER, true);
map.makeUnmodifiable();
return map;
}
@@ -135,35 +122,14 @@ final class DefaultTypeAdapters {
ParameterizedTypeHandlerMap> map =
new ParameterizedTypeHandlerMap>();
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER), true);
- map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER), true);
map.makeUnmodifiable();
return map;
}
@SuppressWarnings("unchecked")
private static ParameterizedTypeHandlerMap> createDefaultInstanceCreators() {
- ParameterizedTypeHandlerMap> map =
- new ParameterizedTypeHandlerMap>();
- DefaultConstructorAllocator allocator = new DefaultConstructorAllocator(50);
-
- // Map Instance Creators
- map.registerForTypeHierarchy(Map.class,
- new DefaultConstructorCreator(LinkedHashMap.class, allocator), true);
-
- // Add Collection type instance creators
- DefaultConstructorCreator listCreator =
- new DefaultConstructorCreator(ArrayList.class, allocator);
- DefaultConstructorCreator queueCreator =
- new DefaultConstructorCreator(LinkedList.class, allocator);
- DefaultConstructorCreator setCreator =
- new DefaultConstructorCreator(HashSet.class, allocator);
- DefaultConstructorCreator sortedSetCreator =
- new DefaultConstructorCreator(TreeSet.class, allocator);
- map.registerForTypeHierarchy(Collection.class, listCreator, true);
- map.registerForTypeHierarchy(Queue.class, queueCreator, true);
- map.registerForTypeHierarchy(Set.class, setCreator, true);
- map.registerForTypeHierarchy(SortedSet.class, sortedSetCreator, true);
-
+ ParameterizedTypeHandlerMap> map
+ = new ParameterizedTypeHandlerMap>();
map.makeUnmodifiable();
return map;
}
@@ -566,33 +532,4 @@ final class DefaultTypeAdapters {
return CharacterTypeAdapter.class.getSimpleName();
}
}
-
- @SuppressWarnings("unchecked")
- private static final class DefaultConstructorCreator implements InstanceCreator {
- private final Class extends T> defaultInstance;
- private final DefaultConstructorAllocator allocator;
-
- public DefaultConstructorCreator(Class extends T> defaultInstance,
- DefaultConstructorAllocator allocator) {
- this.defaultInstance = defaultInstance;
- this.allocator = allocator;
- }
-
- public T createInstance(Type type) {
- Class> rawType = $Gson$Types.getRawType(type);
- try {
- T specificInstance = (T) allocator.newInstance(rawType);
- return (specificInstance == null)
- ? allocator.newInstance(defaultInstance)
- : specificInstance;
- } catch (Exception e) {
- throw new JsonIOException(e);
- }
- }
-
- @Override
- public String toString() {
- return DefaultConstructorCreator.class.getSimpleName();
- }
- }
}
diff --git a/gson/src/main/java/com/google/gson/DelegatingJsonElementVisitor.java b/gson/src/main/java/com/google/gson/DelegatingJsonElementVisitor.java
deleted file mode 100644
index a3970e4d..00000000
--- a/gson/src/main/java/com/google/gson/DelegatingJsonElementVisitor.java
+++ /dev/null
@@ -1,118 +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 com.google.gson.internal.$Gson$Preconditions;
-
-import java.io.IOException;
-
-/**
- * A simple implementation of the {@link JsonElementVisitor} that simply delegates the method
- * invocation onto a {@code delegate} instance of the {@link JsonElementVisitor}. This object
- * can be used to build a chain of visitors such that each Visitor instance can perform some
- * operation on the {@link JsonElement} and then pass on the input to the delegate. This kind
- * of pattern is sometimes referred as a "Chain of Responsibility".
- *
- * The following is an example use case:
- *
- *
- * class JsonEscapingVisitor extends DelegatingJsonElementVisitor {
- * public JsonEscapingVisitor(JsonElementVisitor) {
- * super(visitor);
- * }
- *
- * public void visitPrimitive(JsonPrimitive primitive) {
- * JsonPrimitive escapedPrimitive = escapePrimitiveObject(primitive);
- * super.visitPrimitive(escapedPrimitive);
- * }
- * }
- *
- * JsonElementVisitor visitor = new JsonEscapingVisitor(new FormattingVisitor());
- *
- *
- * @author Joel Leitch
- */
-final class DelegatingJsonElementVisitor implements JsonElementVisitor {
- private final JsonElementVisitor delegate;
-
- protected DelegatingJsonElementVisitor(JsonElementVisitor delegate) {
- this.delegate = $Gson$Preconditions.checkNotNull(delegate);
- }
-
- public void endArray(JsonArray array) throws IOException {
- delegate.endArray(array);
- }
-
- public void endObject(JsonObject object) throws IOException {
- delegate.endObject(object);
- }
-
- public void startArray(JsonArray array) throws IOException {
- delegate.startArray(array);
- }
-
- public void startObject(JsonObject object) throws IOException {
- delegate.startObject(object);
- }
-
- public void visitArrayMember(JsonArray parent, JsonPrimitive member,
- boolean isFirst) throws IOException {
- delegate.visitArrayMember(parent, member, isFirst);
- }
-
- public void visitArrayMember(JsonArray parent, JsonArray member,
- boolean isFirst) throws IOException {
- delegate.visitArrayMember(parent, member, isFirst);
- }
-
- public void visitArrayMember(JsonArray parent, JsonObject member,
- boolean isFirst) throws IOException {
- delegate.visitArrayMember(parent, member, isFirst);
- }
-
- public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
- boolean isFirst) throws IOException {
- delegate.visitObjectMember(parent, memberName, member, isFirst);
- }
-
- public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
- boolean isFirst) throws IOException {
- delegate.visitObjectMember(parent, memberName, member, isFirst);
- }
-
- public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
- boolean isFirst) throws IOException {
- delegate.visitObjectMember(parent, memberName, member, isFirst);
- }
-
- public void visitNullObjectMember(JsonObject parent, String memberName,
- boolean isFirst) throws IOException {
- delegate.visitNullObjectMember(parent, memberName, isFirst);
- }
-
- public void visitPrimitive(JsonPrimitive primitive) throws IOException {
- delegate.visitPrimitive(primitive);
- }
-
- public void visitNull() throws IOException {
- delegate.visitNull();
- }
-
- public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
- delegate.visitNullArrayMember(parent, isFirst);
- }
-}
diff --git a/gson/src/main/java/com/google/gson/FieldAttributes.java b/gson/src/main/java/com/google/gson/FieldAttributes.java
index 0aa47511..1df8f2ff 100644
--- a/gson/src/main/java/com/google/gson/FieldAttributes.java
+++ b/gson/src/main/java/com/google/gson/FieldAttributes.java
@@ -19,6 +19,7 @@ package com.google.gson;
import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.$Gson$Types;
+import com.google.gson.internal.Pair;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java
index ddc70ed8..17eefe2c 100644
--- a/gson/src/main/java/com/google/gson/Gson.java
+++ b/gson/src/main/java/com/google/gson/Gson.java
@@ -16,15 +16,19 @@
package com.google.gson;
+import com.google.gson.internal.ConstructorConstructor;
+import com.google.gson.internal.ParameterizedTypeHandlerMap;
+import com.google.gson.internal.Primitives;
import com.google.gson.internal.Streams;
import com.google.gson.internal.bind.ArrayTypeAdapter;
import com.google.gson.internal.bind.BigDecimalTypeAdapter;
import com.google.gson.internal.bind.BigIntegerTypeAdapter;
-import com.google.gson.internal.bind.CollectionTypeAdapter;
-import com.google.gson.internal.bind.GsonCompatibleMapTypeAdapter;
+import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
+import com.google.gson.internal.bind.ExcludedTypeAdapterFactory;
+import com.google.gson.internal.bind.MapTypeAdapterFactory;
import com.google.gson.internal.bind.MiniGson;
import com.google.gson.internal.bind.ObjectTypeAdapter;
-import com.google.gson.internal.bind.ReflectiveTypeAdapter;
+import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import com.google.gson.internal.bind.TypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.reflect.TypeToken;
@@ -32,7 +36,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.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
@@ -113,7 +117,7 @@ public final class Gson {
private final ExclusionStrategy deserializationExclusionStrategy;
private final ExclusionStrategy serializationExclusionStrategy;
private final FieldNamingStrategy2 fieldNamingPolicy;
- private final MappedObjectConstructor objectConstructor;
+ private final ConstructorConstructor constructorConstructor;
/** Map containing Type or Class objects as keys */
private final ParameterizedTypeHandlerMap> serializers;
@@ -164,7 +168,7 @@ public final class Gson {
*/
public Gson() {
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
- new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
+ DefaultTypeAdapters.getDefaultInstanceCreators(),
false, DefaultTypeAdapters.getAllDefaultSerializers(),
DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false,
false, LongSerializationPolicy.DEFAULT);
@@ -173,7 +177,7 @@ public final class Gson {
Gson(final ExclusionStrategy deserializationExclusionStrategy,
final ExclusionStrategy serializationExclusionStrategy,
final FieldNamingStrategy2 fieldNamingPolicy,
- final MappedObjectConstructor objectConstructor, boolean serializeNulls,
+ final ParameterizedTypeHandlerMap> instanceCreators, boolean serializeNulls,
final ParameterizedTypeHandlerMap> serializers,
final ParameterizedTypeHandlerMap> deserializers,
boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting,
@@ -181,7 +185,7 @@ public final class Gson {
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.fieldNamingPolicy = fieldNamingPolicy;
- this.objectConstructor = objectConstructor;
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.serializers = serializers;
this.deserializers = deserializers;
@@ -196,33 +200,24 @@ public final class Gson {
serializeNulls
serializers
*/
- TypeAdapter.Factory reflectiveTypeAdapterFactory =
- new ReflectiveTypeAdapter.FactoryImpl() {
+ TypeAdapter.Factory reflectiveTypeAdapterFactory
+ = new ReflectiveTypeAdapterFactory(constructorConstructor) {
@Override
public String getFieldName(Class> declaringClazz, Field f, Type declaredType) {
return fieldNamingPolicy.translateName(new FieldAttributes(declaringClazz, f, declaredType));
}
@Override
public boolean serializeField(Class> declaringClazz, Field f, Type declaredType) {
- return !Gson.this.serializationExclusionStrategy.shouldSkipField(
- new FieldAttributes(declaringClazz, f, declaredType));
+ ExclusionStrategy strategy = Gson.this.serializationExclusionStrategy;
+ return !strategy.shouldSkipClass(f.getType())
+ && !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f, declaredType));
}
+
@Override
public boolean deserializeField(Class> declaringClazz, Field f, Type declaredType) {
- return !Gson.this.deserializationExclusionStrategy.shouldSkipField(
- new FieldAttributes(declaringClazz, f, declaredType));
- }
- };
-
- TypeAdapter.Factory excludedTypeFactory = new TypeAdapter.Factory() {
- public TypeAdapter create(MiniGson context, TypeToken type) {
- Class> rawType = type.getRawType();
- if (serializationExclusionStrategy.shouldSkipClass(rawType)
- || deserializationExclusionStrategy.shouldSkipClass(rawType)) {
- return TypeAdapters.EXCLUDED_TYPE_ADAPTER;
- } else {
- return null;
- }
+ ExclusionStrategy strategy = Gson.this.deserializationExclusionStrategy;
+ return !strategy.shouldSkipClass(f.getType())
+ && !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f, declaredType));
}
};
@@ -238,6 +233,8 @@ public final class Gson {
doubleAdapter(serializeSpecialFloatingPointValues)))
.factory(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)))
+ .factory(new ExcludedTypeAdapterFactory(
+ serializationExclusionStrategy, deserializationExclusionStrategy))
.factory(TypeAdapters.STRING_FACTORY)
.factory(TypeAdapters.STRING_BUILDER_FACTORY)
.factory(TypeAdapters.STRING_BUFFER_FACTORY)
@@ -248,11 +245,12 @@ public final class Gson {
.factory(TypeAdapters.INET_ADDRESS_FACTORY)
.typeAdapter(BigDecimal.class, new BigDecimalTypeAdapter())
.typeAdapter(BigInteger.class, new BigIntegerTypeAdapter())
- .factory(excludedTypeFactory)
- .factory(GsonCompatibleMapTypeAdapter.FACTORY)
- .factory(CollectionTypeAdapter.FACTORY)
+ .factory(new MapTypeAdapterFactory(constructorConstructor))
+ .factory(new CollectionTypeAdapterFactory(constructorConstructor))
.factory(ObjectTypeAdapter.FACTORY)
- .factory(new GsonToMiniGsonTypeAdapter(serializers, deserializers, serializeNulls))
+ .factory(new GsonToMiniGsonTypeAdapterFactory(serializers, deserializers,
+ new JsonDeserializationContext(this), new JsonSerializationContext(this), serializeNulls
+ ))
.factory(ArrayTypeAdapter.FACTORY)
.factory(reflectiveTypeAdapterFactory);
@@ -265,9 +263,17 @@ public final class Gson {
}
return new TypeAdapter() {
@Override public Double read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
return reader.nextDouble();
}
@Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
double doubleValue = value.doubleValue();
checkValidFloatingPoint(doubleValue);
writer.value(value);
@@ -281,9 +287,17 @@ public final class Gson {
}
return new TypeAdapter() {
@Override public Float read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
return (float) reader.nextDouble();
}
@Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
float floatValue = value.floatValue();
checkValidFloatingPoint(floatValue);
writer.value(value);
@@ -305,9 +319,17 @@ public final class Gson {
}
return new TypeAdapter() {
@Override public Number read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
return reader.nextLong();
}
@Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
writer.value(value.toString());
}
};
@@ -640,11 +662,23 @@ public final class Gson {
*/
@SuppressWarnings("unchecked")
public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
+ boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
+ reader.peek();
+ isEmpty = false;
TypeAdapter typeAdapter = (TypeAdapter) miniGson.getAdapter(TypeToken.get(typeOfT));
return typeAdapter.read(reader);
+ } catch (EOFException e) {
+ /*
+ * For compatibility with JSON 1.5 and earlier, we return null for empty
+ * documents instead of throwing.
+ */
+ if (isEmpty) {
+ return null;
+ }
+ throw new JsonSyntaxException(e);
} catch (IOException e) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
@@ -710,8 +744,9 @@ public final class Gson {
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
// just a utility class around instance creators, and its toString() only displays them.
- .append(",instanceCreators:").append(objectConstructor)
+ .append(",instanceCreators:").append(constructorConstructor)
.append("}");
return sb.toString();
}
+
}
diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java
index cdd123cc..09f580c0 100644
--- a/gson/src/main/java/com/google/gson/GsonBuilder.java
+++ b/gson/src/main/java/com/google/gson/GsonBuilder.java
@@ -18,6 +18,8 @@ package com.google.gson;
import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
import com.google.gson.internal.$Gson$Preconditions;
+import com.google.gson.internal.ParameterizedTypeHandlerMap;
+import com.google.gson.internal.Primitives;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
@@ -678,6 +680,7 @@ public final class GsonBuilder {
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers);
+ customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers());
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers());
ParameterizedTypeHandlerMap> customInstanceCreators =
@@ -688,11 +691,9 @@ public final class GsonBuilder {
customDeserializers.makeUnmodifiable();
instanceCreators.makeUnmodifiable();
- MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
-
return new Gson(new DisjunctionExclusionStrategy(deserializationStrategies),
new DisjunctionExclusionStrategy(serializationStrategies),
- fieldNamingPolicy, objConstructor, serializeNulls,
+ fieldNamingPolicy, instanceCreators, serializeNulls,
customSerializers, customDeserializers, generateNonExecutableJson, escapeHtmlChars,
prettyPrinting, serializeSpecialFloatingPointValues, longSerializationPolicy);
}
diff --git a/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapter.java b/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapter.java
deleted file mode 100644
index 0daa1ff4..00000000
--- a/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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;
-
-import java.io.IOException;
-import java.lang.reflect.Type;
-
-import com.google.gson.internal.Streams;
-import com.google.gson.internal.bind.MiniGson;
-import com.google.gson.internal.bind.TypeAdapter;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-final class GsonToMiniGsonTypeAdapter implements TypeAdapter.Factory {
- private final ParameterizedTypeHandlerMap> serializers;
- private final ParameterizedTypeHandlerMap> deserializers;
- private final boolean serializeNulls;
-
- GsonToMiniGsonTypeAdapter(ParameterizedTypeHandlerMap> serializers,
- ParameterizedTypeHandlerMap> deserializers, boolean serializeNulls) {
- this.serializers = serializers;
- this.deserializers = deserializers;
- this.serializeNulls = serializeNulls;
- }
-
- public TypeAdapter create(final MiniGson miniGson, TypeToken type) {
- final Type typeOfT = type.getType();
- final JsonSerializer serializer = serializers.getHandlerFor(typeOfT, false);
- final JsonDeserializer deserializer = deserializers.getHandlerFor(typeOfT, false);
- if (serializer == null && deserializer == null) {
- return null;
- }
- return new TypeAdapter() {
- @Override
- public Object read(JsonReader reader) throws IOException {
- if (deserializer == null) {
- // TODO: handle if deserializer is null
- throw new UnsupportedOperationException();
- }
- JsonElement value = Streams.parse(reader);
- if (value.isJsonNull()) {
- return null;
- }
- return deserializer.deserialize(value, typeOfT, createDeserializationContext(miniGson));
- }
- @Override
- public void write(JsonWriter writer, Object value) throws IOException {
- if (serializer == null) {
- // TODO: handle if serializer is null
- throw new UnsupportedOperationException();
- }
- if (value == null) {
- writer.nullValue();
- return;
- }
- JsonElement element = serializer.serialize(value, typeOfT, createSerializationContext(miniGson));
- Streams.write(element, serializeNulls, writer);
- }
- };
- }
-
- public JsonSerializationContext createSerializationContext(final MiniGson miniGson) {
- return new JsonSerializationContext() {
- @Override
- JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType, boolean defaultOnly) {
- TypeToken typeToken = TypeToken.get(typeOfSrc);
- return miniGson.getAdapter(typeToken).toJsonElement(src);
- }
- };
- }
- public JsonDeserializationContext createDeserializationContext(final MiniGson miniGson) {
- return new JsonDeserializationContext() {
- @Override
- public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
- TypeToken typeToken = TypeToken.get(typeOfT);
- return (T) miniGson.getAdapter(typeToken).fromJsonElement(json);
- }
-
- @Override public T construct(Type type) {
- throw new UnsupportedOperationException();
- }
-
- @Override public Object constructArray(Type type, int length) {
- throw new UnsupportedOperationException();
- }
-
- @Override public T deserializeDefault(JsonElement json, Type typeOfT) throws JsonParseException {
- throw new UnsupportedOperationException();
- }
- };
- }
-}
diff --git a/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapterFactory.java
new file mode 100644
index 00000000..77fdd02a
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/GsonToMiniGsonTypeAdapterFactory.java
@@ -0,0 +1,99 @@
+/*
+ * 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;
+
+import com.google.gson.internal.ParameterizedTypeHandlerMap;
+import com.google.gson.internal.Streams;
+import com.google.gson.internal.bind.MiniGson;
+import com.google.gson.internal.bind.TypeAdapter;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+final class GsonToMiniGsonTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ParameterizedTypeHandlerMap> serializers;
+ private final ParameterizedTypeHandlerMap> deserializers;
+ private final JsonDeserializationContext deserializationContext;
+ private final JsonSerializationContext serializationContext;
+ private final boolean serializeNulls;
+
+ GsonToMiniGsonTypeAdapterFactory(ParameterizedTypeHandlerMap> serializers,
+ ParameterizedTypeHandlerMap> deserializers,
+ JsonDeserializationContext deserializationContext,
+ JsonSerializationContext serializationContext, boolean serializeNulls) {
+ this.serializers = serializers;
+ this.deserializers = deserializers;
+ this.serializeNulls = serializeNulls;
+ this.deserializationContext = deserializationContext;
+ this.serializationContext = serializationContext;
+ }
+
+ public TypeAdapter create(final MiniGson context, final TypeToken typeToken) {
+ final Type type = typeToken.getType();
+
+ @SuppressWarnings("unchecked") // guaranteed to match typeOfT
+ final JsonSerializer serializer
+ = (JsonSerializer) serializers.getHandlerFor(type, false);
+ @SuppressWarnings("unchecked") // guaranteed to match typeOfT
+ final JsonDeserializer deserializer
+ = (JsonDeserializer) deserializers.getHandlerFor(type, false);
+
+ if (serializer == null && deserializer == null) {
+ return null;
+ }
+
+ return new TypeAdapter() {
+ /**
+ * The delegate is lazily created because it may not be needed, and
+ * creating it may fail.
+ */
+ private TypeAdapter delegate;
+
+ @Override public T read(JsonReader reader) throws IOException {
+ if (deserializer == null) {
+ return delegate().read(reader);
+ }
+ JsonElement value = Streams.parse(reader);
+ if (value.isJsonNull()) {
+ return null;
+ }
+ return deserializer.deserialize(value, type, deserializationContext);
+ }
+
+ @Override public void write(JsonWriter writer, T value) throws IOException {
+ if (serializer == null) {
+ delegate().write(writer, value);
+ return;
+ }
+ if (value == null) {
+ writer.nullValue();
+ return;
+ }
+ JsonElement element = serializer.serialize(value, type, serializationContext);
+ Streams.write(element, serializeNulls, writer);
+ }
+
+ private TypeAdapter delegate() {
+ TypeAdapter d = delegate;
+ return d != null
+ ? d
+ : (delegate = context.getNextAdapter(GsonToMiniGsonTypeAdapterFactory.this, typeToken));
+ }
+ };
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/JsonArrayDeserializationVisitor.java b/gson/src/main/java/com/google/gson/JsonArrayDeserializationVisitor.java
deleted file mode 100644
index c7806acf..00000000
--- a/gson/src/main/java/com/google/gson/JsonArrayDeserializationVisitor.java
+++ /dev/null
@@ -1,111 +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 com.google.gson.internal.$Gson$Types;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Type;
-
-/**
- * A visitor that populates fields of an object with data from its equivalent
- * JSON representation
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- */
-final class JsonArrayDeserializationVisitor extends JsonDeserializationVisitor {
-
- JsonArrayDeserializationVisitor(JsonArray jsonArray, Type arrayType,
- ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
- ObjectConstructor objectConstructor,
- ParameterizedTypeHandlerMap> deserializers,
- JsonDeserializationContext context) {
- super(jsonArray, arrayType, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- protected T constructTarget() {
- if (!json.isJsonArray()) {
- throw new JsonParseException("Expecting array found: " + json);
- }
- JsonArray jsonArray = json.getAsJsonArray();
- if ($Gson$Types.isArray(targetType)) {
- // We know that we are getting back an array of the required type, so
- // this typecasting is safe.
- return (T) objectConstructor.constructArray($Gson$Types.getArrayComponentType(targetType),
- jsonArray.size());
- }
- // is a collection
- return (T) objectConstructor.construct($Gson$Types.getRawType(targetType));
- }
-
- public void visitArray(Object array, Type arrayType) {
- if (!json.isJsonArray()) {
- throw new JsonParseException("Expecting array found: " + json);
- }
- JsonArray jsonArray = json.getAsJsonArray();
- for (int i = 0; i < jsonArray.size(); i++) {
- JsonElement jsonChild = jsonArray.get(i);
- Object child;
-
- if (jsonChild == null || jsonChild.isJsonNull()) {
- child = null;
- } else if (jsonChild instanceof JsonObject) {
- child = visitChildAsObject($Gson$Types.getArrayComponentType(arrayType), jsonChild);
- } else if (jsonChild instanceof JsonArray) {
- child = visitChildAsArray($Gson$Types.getArrayComponentType(arrayType),
- jsonChild.getAsJsonArray());
- } else if (jsonChild instanceof JsonPrimitive) {
- child = visitChildAsObject($Gson$Types.getArrayComponentType(arrayType),
- jsonChild.getAsJsonPrimitive());
- } else {
- throw new IllegalStateException();
- }
- Array.set(array, i, child);
- }
- }
-
- // We should not implement any other method from Visitor interface since
- // all other methods should be invoked on JsonObjectDeserializationVisitor
- // instead.
-
- public void startVisitingObject(Object node) {
- throw new JsonParseException("Expecting array but found object: " + node);
- }
-
- public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
- throw new JsonParseException("Expecting array but found array field " + f.getName() + ": "
- + obj);
- }
-
- public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
- throw new JsonParseException("Expecting array but found object field " + f.getName() + ": "
- + obj);
- }
-
- public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField, Object parent) {
- throw new JsonParseException("Expecting array but found field " + f.getName() + ": "
- + parent);
- }
-
- public void visitPrimitive(Object primitive) {
- throw new JsonParseException(
- "Type information is unavailable, and the target is not a primitive: " + json);
- }
-}
diff --git a/gson/src/main/java/com/google/gson/JsonDeserializationContext.java b/gson/src/main/java/com/google/gson/JsonDeserializationContext.java
index 3bfbe763..578e6e89 100644
--- a/gson/src/main/java/com/google/gson/JsonDeserializationContext.java
+++ b/gson/src/main/java/com/google/gson/JsonDeserializationContext.java
@@ -27,23 +27,10 @@ import java.lang.reflect.Type;
* @author Joel Leitch
*/
public class JsonDeserializationContext {
- private final ObjectNavigator objectNavigator;
- private final FieldNamingStrategy2 fieldNamingPolicy;
- private final ParameterizedTypeHandlerMap> deserializers;
- private final MappedObjectConstructor objectConstructor;
+ private final Gson gson;
- JsonDeserializationContext(ObjectNavigator objectNavigator,
- FieldNamingStrategy2 fieldNamingPolicy,
- ParameterizedTypeHandlerMap> deserializers,
- MappedObjectConstructor objectConstructor) {
- this.objectNavigator = objectNavigator;
- this.fieldNamingPolicy = fieldNamingPolicy;
- this.deserializers = deserializers;
- this.objectConstructor = objectConstructor;
- }
-
- JsonDeserializationContext() {
- this(null, null, null, null);
+ JsonDeserializationContext(Gson gson) {
+ this.gson = gson;
}
/**
@@ -51,41 +38,11 @@ public class JsonDeserializationContext {
*/
@SuppressWarnings("unchecked") @Deprecated
public T construct(Type type) {
- Object instance = objectConstructor.construct(type);
- return (T) instance;
+ throw new UnsupportedOperationException();
}
public Object constructArray(Type type, int length) {
- return objectConstructor.constructArray(type, length);
- }
-
-
- private T fromJsonArray(Type arrayType, JsonArray jsonArray,
- JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
- JsonArrayDeserializationVisitor visitor = new JsonArrayDeserializationVisitor(
- jsonArray, arrayType, objectNavigator, fieldNamingPolicy,
- objectConstructor, deserializers, context);
- objectNavigator.accept(new ObjectTypePair(null, arrayType, true, systemOnly), visitor);
- return visitor.getTarget();
- }
-
- private T fromJsonObject(Type typeOfT, JsonObject jsonObject,
- JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
- JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor(
- jsonObject, typeOfT, objectNavigator, fieldNamingPolicy,
- objectConstructor, deserializers, context);
- objectNavigator.accept(new ObjectTypePair(null, typeOfT, true, systemOnly), visitor);
- return visitor.getTarget();
- }
-
- @SuppressWarnings("unchecked")
- private T fromJsonPrimitive(Type typeOfT, JsonPrimitive json,
- JsonDeserializationContext context, boolean systemOnly) throws JsonParseException {
- JsonObjectDeserializationVisitor visitor = new JsonObjectDeserializationVisitor(
- json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
- objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true, systemOnly), visitor);
- Object target = visitor.getTarget();
- return (T) target;
+ throw new UnsupportedOperationException();
}
/**
@@ -102,37 +59,11 @@ public class JsonDeserializationContext {
*/
@SuppressWarnings("unchecked")
public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
- if (json == null || json.isJsonNull()) {
- return null;
- } else if (json.isJsonArray()) {
- Object array = fromJsonArray(typeOfT, json.getAsJsonArray(), this, false);
- return (T) array;
- } else if (json.isJsonObject()) {
- Object object = fromJsonObject(typeOfT, json.getAsJsonObject(), this, false);
- return (T) object;
- } else if (json.isJsonPrimitive()) {
- Object primitive = fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this, false);
- return (T) primitive;
- } else {
- throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");
- }
+ return gson.fromJson(json, typeOfT);
}
@SuppressWarnings("unchecked")
public 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;
- } else {
- throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");
- }
+ throw new UnsupportedOperationException();
}
}
\ No newline at end of file
diff --git a/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java b/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java
deleted file mode 100644
index 033bf20d..00000000
--- a/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java
+++ /dev/null
@@ -1,115 +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 com.google.gson.internal.$Gson$Preconditions;
-
-import java.lang.reflect.Type;
-
-/**
- * Abstract data value container for the {@link ObjectNavigator.Visitor}
- * implementations. This class exposes the {@link #getTarget()} method
- * which returns the class that was visited by this object.
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- */
-abstract class JsonDeserializationVisitor implements ObjectNavigator.Visitor {
-
- protected final ObjectNavigator objectNavigator;
- protected final FieldNamingStrategy2 fieldNamingPolicy;
- protected final ObjectConstructor objectConstructor;
- protected final ParameterizedTypeHandlerMap> deserializers;
- protected T target;
- protected final JsonElement json;
- protected final Type targetType;
- protected final JsonDeserializationContext context;
- protected boolean constructed;
-
- JsonDeserializationVisitor(JsonElement json, Type targetType,
- ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
- ObjectConstructor objectConstructor,
- ParameterizedTypeHandlerMap> deserializers,
- JsonDeserializationContext context) {
- this.targetType = targetType;
- this.objectNavigator = objectNavigator;
- this.fieldNamingPolicy = fieldNamingPolicy;
- this.objectConstructor = objectConstructor;
- this.deserializers = deserializers;
- this.json = $Gson$Preconditions.checkNotNull(json);
- this.context = context;
- this.constructed = false;
- }
-
- public T getTarget() {
- if (!constructed) {
- target = constructTarget();
- constructed = true;
- }
- return target;
- }
-
- protected abstract T constructTarget();
-
- public void start(ObjectTypePair node) {
- }
-
- public void end(ObjectTypePair node) {
- }
-
- @SuppressWarnings("unchecked")
- public final boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
- Pair, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
- if (pair == null) {
- return false;
- }
- Object value = invokeCustomDeserializer(json, pair);
- target = (T) value;
- constructed = true;
- return true;
- }
-
- protected Object invokeCustomDeserializer(JsonElement element,
- Pair, ObjectTypePair> pair) {
- if (element == null || element.isJsonNull()) {
- return null;
- }
- Type objType = pair.second.type;
- return (pair.first).deserialize(element, objType, context);
- }
-
- final Object visitChildAsObject(Type childType, JsonElement jsonChild) {
- JsonDeserializationVisitor> childVisitor =
- new JsonObjectDeserializationVisitor(jsonChild, childType,
- objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
- return visitChild(childType, childVisitor);
- }
-
- final Object visitChildAsArray(Type childType, JsonArray jsonChild) {
- JsonDeserializationVisitor> childVisitor =
- new JsonArrayDeserializationVisitor(jsonChild.getAsJsonArray(), childType,
- objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
- return visitChild(childType, childVisitor);
- }
-
- private Object visitChild(Type type, JsonDeserializationVisitor> childVisitor) {
- objectNavigator.accept(new ObjectTypePair(null, type, false, false), childVisitor);
- // the underlying object may have changed during the construction phase
- // This happens primarily because of custom deserializers
- return childVisitor.getTarget();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/JsonElement.java b/gson/src/main/java/com/google/gson/JsonElement.java
index 79938598..0a909c7b 100644
--- a/gson/src/main/java/com/google/gson/JsonElement.java
+++ b/gson/src/main/java/com/google/gson/JsonElement.java
@@ -143,7 +143,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public boolean getAsBoolean() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -156,7 +156,7 @@ public abstract class JsonElement {
* more than a single element.
*/
Boolean getAsBooleanWrapper() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -169,7 +169,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public Number getAsNumber() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -182,7 +182,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public String getAsString() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -195,7 +195,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public double getAsDouble() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -208,7 +208,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public float getAsFloat() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -221,7 +221,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public long getAsLong() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -234,7 +234,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public int getAsInt() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -248,7 +248,7 @@ public abstract class JsonElement {
* @since 1.3
*/
public byte getAsByte() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -262,7 +262,7 @@ public abstract class JsonElement {
* @since 1.3
*/
public char getAsCharacter() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -276,7 +276,7 @@ public abstract class JsonElement {
* @since 1.2
*/
public BigDecimal getAsBigDecimal() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -290,7 +290,7 @@ public abstract class JsonElement {
* @since 1.2
*/
public BigInteger getAsBigInteger() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -303,7 +303,7 @@ public abstract class JsonElement {
* more than a single element.
*/
public short getAsShort() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
@@ -316,7 +316,7 @@ public abstract class JsonElement {
* more than a single element.
*/
Object getAsObject() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
diff --git a/gson/src/main/java/com/google/gson/JsonObjectDeserializationVisitor.java b/gson/src/main/java/com/google/gson/JsonObjectDeserializationVisitor.java
deleted file mode 100644
index 173dd8a6..00000000
--- a/gson/src/main/java/com/google/gson/JsonObjectDeserializationVisitor.java
+++ /dev/null
@@ -1,136 +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;
-
-/**
- * A visitor that populates fields of an object with data from its equivalent
- * JSON representation
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- */
-final class JsonObjectDeserializationVisitor extends JsonDeserializationVisitor {
-
- JsonObjectDeserializationVisitor(JsonElement json, Type type,
- ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
- ObjectConstructor objectConstructor,
- ParameterizedTypeHandlerMap> deserializers,
- JsonDeserializationContext context) {
- super(json, type, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- protected T constructTarget() {
- return (T) objectConstructor.construct(targetType);
- }
-
- public void startVisitingObject(Object node) {
- // do nothing
- }
-
- public void visitArray(Object array, Type componentType) {
- // should not be called since this case should invoke JsonArrayDeserializationVisitor
- throw new JsonParseException("Expecting object but found array: " + array);
- }
-
- public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
- try {
- if (!json.isJsonObject()) {
- throw new JsonParseException("Expecting object found: " + json);
- }
- JsonObject jsonObject = json.getAsJsonObject();
- String fName = getFieldName(f);
- JsonElement jsonChild = jsonObject.get(fName);
- if (jsonChild != null) {
- Object child = visitChildAsObject(typeOfF, jsonChild);
- f.set(obj, child);
- } else {
- f.set(obj, null);
- }
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
- try {
- if (!json.isJsonObject()) {
- throw new JsonParseException("Expecting object found: " + json);
- }
- JsonObject jsonObject = json.getAsJsonObject();
- String fName = getFieldName(f);
- JsonArray jsonChild = (JsonArray) jsonObject.get(fName);
- if (jsonChild != null) {
- Object array = visitChildAsArray(typeOfF, jsonChild);
- f.set(obj, array);
- } else {
- f.set(obj, null);
- }
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- private String getFieldName(FieldAttributes f) {
- return fieldNamingPolicy.translateName(f);
- }
-
- public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type declaredTypeOfField, Object parent) {
- try {
- String fName = getFieldName(f);
- if (!json.isJsonObject()) {
- throw new JsonParseException("Expecting object found: " + json);
- }
- JsonElement child = json.getAsJsonObject().get(fName);
- boolean isPrimitive = Primitives.isPrimitive(declaredTypeOfField);
- if (child == null) { // Child will be null if the field wasn't present in Json
- return true;
- } else if (child.isJsonNull()) {
- if (!isPrimitive) {
- f.set(parent, null);
- }
- return true;
- }
- ObjectTypePair objTypePair = new ObjectTypePair(null, declaredTypeOfField, false, false);
- Pair, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
- if (pair == null) {
- return false;
- }
- Object value = invokeCustomDeserializer(child, pair);
- if (value != null || !isPrimitive) {
- f.set(parent, value);
- }
- return true;
- } catch (IllegalAccessException e) {
- throw new RuntimeException();
- }
- }
-
- @SuppressWarnings("unchecked")
- public void visitPrimitive(Object primitive) {
- if (!json.isJsonPrimitive()) {
- throw new JsonParseException(
- "Type information is unavailable, and the target object is not a primitive: " + json);
- }
- JsonPrimitive prim = json.getAsJsonPrimitive();
- target = (T) prim.getAsObject();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/JsonSerializationContext.java b/gson/src/main/java/com/google/gson/JsonSerializationContext.java
index 7198a1bf..e5fee93d 100644
--- a/gson/src/main/java/com/google/gson/JsonSerializationContext.java
+++ b/gson/src/main/java/com/google/gson/JsonSerializationContext.java
@@ -27,24 +27,10 @@ import java.lang.reflect.Type;
*/
public class JsonSerializationContext {
- private final ObjectNavigator objectNavigator;
- private final FieldNamingStrategy2 fieldNamingPolicy;
- private final ParameterizedTypeHandlerMap> serializers;
- private final boolean serializeNulls;
- private final MemoryRefStack ancestors;
+ private final Gson gson;
- 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();
- }
-
- JsonSerializationContext() {
- this(null, null, false, null);
+ JsonSerializationContext(Gson gson) {
+ this.gson = gson;
}
/**
@@ -54,10 +40,7 @@ public class JsonSerializationContext {
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src) {
- if (src == null) {
- return JsonNull.INSTANCE;
- }
- return serialize(src, src.getClass(), false, false);
+ return gson.toJsonTree(src);
}
/**
@@ -71,21 +54,10 @@ public class JsonSerializationContext {
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src, Type typeOfSrc) {
- return serialize(src, typeOfSrc, true, false);
+ return gson.toJsonTree(src, typeOfSrc);
}
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) {
- return JsonNull.INSTANCE;
- }
- JsonSerializationVisitor visitor = new JsonSerializationVisitor(
- objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors);
- ObjectTypePair objTypePair = new ObjectTypePair(src, typeOfSrc, preserveType, defaultOnly);
- objectNavigator.accept(objTypePair, visitor);
- return visitor.getJsonElement();
+ throw new UnsupportedOperationException();
}
}
\ No newline at end of file
diff --git a/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java b/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java
deleted file mode 100644
index d29e6904..00000000
--- a/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java
+++ /dev/null
@@ -1,236 +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 com.google.gson.internal.$Gson$Types;
-import com.google.gson.internal.$Gson$Preconditions;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Type;
-
-/**
- * A visitor that adds JSON elements corresponding to each field of an object
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- */
-final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
-
- private final ObjectNavigator objectNavigator;
- private final FieldNamingStrategy2 fieldNamingPolicy;
- private final ParameterizedTypeHandlerMap> serializers;
- private final boolean serializeNulls;
- private final JsonSerializationContext context;
- private final MemoryRefStack ancestors;
- private JsonElement root;
-
- JsonSerializationVisitor(ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
- boolean serializeNulls, ParameterizedTypeHandlerMap> serializers,
- JsonSerializationContext context, MemoryRefStack ancestors) {
- this.objectNavigator = objectNavigator;
- this.fieldNamingPolicy = fieldNamingPolicy;
- this.serializeNulls = serializeNulls;
- this.serializers = serializers;
- this.context = context;
- this.ancestors = ancestors;
- }
-
- public Object getTarget() {
- return null;
- }
-
- public void start(ObjectTypePair node) {
- if (node == null || node.isSystemOnly()) {
- return;
- }
- if (ancestors.contains(node)) {
- throw new CircularReferenceException(node);
- }
- ancestors.push(node);
- }
-
- public void end(ObjectTypePair node) {
- if (node != null && !node.isSystemOnly()) {
- ancestors.pop();
- }
- }
-
- public void startVisitingObject(Object node) {
- assignToRoot(new JsonObject());
- }
-
- public void visitArray(Object array, Type arrayType) {
- assignToRoot(new JsonArray());
- int length = Array.getLength(array);
- Type componentType = $Gson$Types.getArrayComponentType(arrayType);
- for (int i = 0; i < length; ++i) {
- Object child = Array.get(array, i);
- // we should not get more specific component type yet since it is possible
- // that a custom serializer is registered for the componentType
- addAsArrayElement(new ObjectTypePair(child, componentType, false, false));
- }
- }
-
- public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
- try {
- if (isFieldNull(f, obj)) {
- if (serializeNulls) {
- addChildAsElement(f, JsonNull.INSTANCE);
- }
- } else {
- Object array = getFieldValue(f, obj);
- addAsChildOfObject(f, new ObjectTypePair(array, typeOfF, false, false));
- }
- } catch (CircularReferenceException e) {
- throw e.createDetailedException(f);
- }
- }
-
- public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
- try {
- if (isFieldNull(f, obj)) {
- if (serializeNulls) {
- addChildAsElement(f, JsonNull.INSTANCE);
- }
- } else {
- Object fieldValue = getFieldValue(f, obj);
- // we should not get more specific component type yet since it is
- // possible that a custom
- // serializer is registered for the componentType
- addAsChildOfObject(f, new ObjectTypePair(fieldValue, typeOfF, false, false));
- }
- } catch (CircularReferenceException e) {
- throw e.createDetailedException(f);
- }
- }
-
- public void visitPrimitive(Object obj) {
- JsonElement json = obj == null ? JsonNull.INSTANCE : new JsonPrimitive(obj);
- assignToRoot(json);
- }
-
- private void addAsChildOfObject(FieldAttributes f, ObjectTypePair fieldValuePair) {
- JsonElement childElement = getJsonElementForChild(fieldValuePair);
- addChildAsElement(f, childElement);
- }
-
- private void addChildAsElement(FieldAttributes f, JsonElement childElement) {
- root.getAsJsonObject().add(fieldNamingPolicy.translateName(f), childElement);
- }
-
- private void addAsArrayElement(ObjectTypePair elementTypePair) {
- if (elementTypePair.getObject() == null) {
- root.getAsJsonArray().add(JsonNull.INSTANCE);
- } else {
- JsonElement childElement = getJsonElementForChild(elementTypePair);
- root.getAsJsonArray().add(childElement);
- }
- }
-
- private JsonElement getJsonElementForChild(ObjectTypePair fieldValueTypePair) {
- JsonSerializationVisitor childVisitor = new JsonSerializationVisitor(
- objectNavigator, fieldNamingPolicy, serializeNulls, serializers, context, ancestors);
- objectNavigator.accept(fieldValueTypePair, childVisitor);
- return childVisitor.getJsonElement();
- }
-
- public boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
- try {
- Object obj = objTypePair.getObject();
- if (obj == null) {
- if (serializeNulls) {
- assignToRoot(JsonNull.INSTANCE);
- }
- return true;
- }
- JsonElement element = findAndInvokeCustomSerializer(objTypePair);
- if (element != null) {
- assignToRoot(element);
- return true;
- }
- return false;
- } catch (CircularReferenceException e) {
- throw e.createDetailedException(null);
- }
- }
-
- /**
- * objTypePair.getObject() must not be null
- */
- @SuppressWarnings("unchecked")
- private JsonElement findAndInvokeCustomSerializer(ObjectTypePair objTypePair) {
- Pair,ObjectTypePair> pair = objTypePair.getMatchingHandler(serializers);
- if (pair == null) {
- return null;
- }
- JsonSerializer serializer = pair.first;
- objTypePair = pair.second;
- start(objTypePair);
- try {
- JsonElement element =
- serializer.serialize(objTypePair.getObject(), objTypePair.getType(), context);
- return element == null ? JsonNull.INSTANCE : element;
- } finally {
- end(objTypePair);
- }
- }
-
- public boolean visitFieldUsingCustomHandler(
- FieldAttributes f, Type declaredTypeOfField, Object parent) {
- try {
- $Gson$Preconditions.checkState(root.isJsonObject());
- Object obj = f.get(parent);
- if (obj == null) {
- if (serializeNulls) {
- addChildAsElement(f, JsonNull.INSTANCE);
- }
- return true;
- }
- ObjectTypePair objTypePair = new ObjectTypePair(obj, declaredTypeOfField, false, false);
- JsonElement child = findAndInvokeCustomSerializer(objTypePair);
- if (child != null) {
- addChildAsElement(f, child);
- return true;
- }
- return false;
- } catch (IllegalAccessException e) {
- throw new RuntimeException();
- } catch (CircularReferenceException e) {
- throw e.createDetailedException(f);
- }
- }
-
- private void assignToRoot(JsonElement newRoot) {
- root = $Gson$Preconditions.checkNotNull(newRoot);
- }
-
- private boolean isFieldNull(FieldAttributes f, Object obj) {
- return getFieldValue(f, obj) == null;
- }
-
- private Object getFieldValue(FieldAttributes f, Object obj) {
- try {
- return f.get(obj);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- public JsonElement getJsonElement() {
- return root;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/JsonTreeNavigator.java b/gson/src/main/java/com/google/gson/JsonTreeNavigator.java
deleted file mode 100644
index 992de504..00000000
--- a/gson/src/main/java/com/google/gson/JsonTreeNavigator.java
+++ /dev/null
@@ -1,111 +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.io.IOException;
-import java.util.Map;
-
-/**
- * A navigator to navigate a tree of JsonElement nodes in Depth-first order
- *
- * @author Inderjeet Singh
- */
-final class JsonTreeNavigator {
- private final JsonElementVisitor visitor;
- private final boolean visitNulls;
-
- JsonTreeNavigator(JsonElementVisitor visitor, boolean visitNulls) {
- this.visitor = visitor;
- this.visitNulls = visitNulls;
- }
-
- public void navigate(JsonElement element) throws IOException {
- if (element.isJsonNull()) {
- visitor.visitNull();
- } else if (element.isJsonArray()) {
- JsonArray array = element.getAsJsonArray();
- visitor.startArray(array);
- boolean isFirst = true;
- for (JsonElement child : array) {
- visitChild(array, child, isFirst);
- if (isFirst) {
- isFirst = false;
- }
- }
- visitor.endArray(array);
- } else if (element.isJsonObject()) {
- JsonObject object = element.getAsJsonObject();
- visitor.startObject(object);
- boolean isFirst = true;
- for (Map.Entry member : object.entrySet()) {
- boolean visited = visitChild(object, member.getKey(), member.getValue(), isFirst);
- if (visited && isFirst) {
- isFirst = false;
- }
- }
- visitor.endObject(object);
- } else { // must be JsonPrimitive
- visitor.visitPrimitive(element.getAsJsonPrimitive());
- }
- }
-
- /**
- * Returns true if the child was visited, false if it was skipped.
- */
- private boolean visitChild(JsonObject parent, String childName, JsonElement child,
- boolean isFirst) throws IOException {
- if (child.isJsonNull()) {
- if (visitNulls) {
- visitor.visitNullObjectMember(parent, childName, isFirst);
- navigate(child.getAsJsonNull());
- } else { // Null value is being skipped.
- return false;
- }
- } else if (child.isJsonArray()) {
- JsonArray childAsArray = child.getAsJsonArray();
- visitor.visitObjectMember(parent, childName, childAsArray, isFirst);
- navigate(childAsArray);
- } else if (child.isJsonObject()) {
- JsonObject childAsObject = child.getAsJsonObject();
- visitor.visitObjectMember(parent, childName, childAsObject, isFirst);
- navigate(childAsObject);
- } else { // is a JsonPrimitive
- visitor.visitObjectMember(parent, childName, child.getAsJsonPrimitive(), isFirst);
- }
- return true;
- }
-
- /**
- * Returns true if the child was visited, false if it was skipped.
- */
- private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) throws IOException {
- if (child.isJsonNull()) {
- visitor.visitNullArrayMember(parent, isFirst);
- navigate(child);
- } else if (child.isJsonArray()) {
- JsonArray childAsArray = child.getAsJsonArray();
- visitor.visitArrayMember(parent, childAsArray, isFirst);
- navigate(childAsArray);
- } else if (child.isJsonObject()) {
- JsonObject childAsObject = child.getAsJsonObject();
- visitor.visitArrayMember(parent, childAsObject, isFirst);
- navigate(childAsObject);
- } else { // is a JsonPrimitive
- visitor.visitArrayMember(parent, child.getAsJsonPrimitive(), isFirst);
- }
- }
-}
diff --git a/gson/src/main/java/com/google/gson/MapAsArrayTypeAdapter.java b/gson/src/main/java/com/google/gson/MapAsArrayTypeAdapter.java
index aba1f6a5..6d2a2511 100644
--- a/gson/src/main/java/com/google/gson/MapAsArrayTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/MapAsArrayTypeAdapter.java
@@ -16,10 +16,7 @@
package com.google.gson;
-import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
/**
@@ -90,79 +87,16 @@ import java.util.Map;
* object.
*/
final class MapAsArrayTypeAdapter
- extends BaseMapTypeAdapter
implements JsonSerializer>, JsonDeserializer> {
public Map, ?> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
- Map result = constructMapType(typeOfT, context);
- Type[] keyAndValueType = typeToTypeArguments(typeOfT);
- if (json.isJsonArray()) {
- JsonArray array = json.getAsJsonArray();
- for (int i = 0; i < array.size(); i++) {
- JsonArray entryArray = array.get(i).getAsJsonArray();
- Object k = context.deserialize(entryArray.get(0), keyAndValueType[0]);
- Object v = context.deserialize(entryArray.get(1), keyAndValueType[1]);
- result.put(k, v);
- }
- checkSize(array, array.size(), result, result.size());
- } else {
- JsonObject object = json.getAsJsonObject();
- for (Map.Entry entry : object.entrySet()) {
- Object k = context.deserialize(new JsonPrimitive(entry.getKey()), keyAndValueType[0]);
- Object v = context.deserialize(entry.getValue(), keyAndValueType[1]);
- result.put(k, v);
- }
- checkSize(object, object.entrySet().size(), result, result.size());
- }
- return result;
+ // TODO
+ throw new UnsupportedOperationException();
}
public JsonElement serialize(Map, ?> src, Type typeOfSrc, JsonSerializationContext context) {
- Type[] keyAndValueType = typeToTypeArguments(typeOfSrc);
- boolean serializeAsArray = false;
- List keysAndValues = new ArrayList();
- for (Map.Entry, ?> entry : src.entrySet()) {
- JsonElement key = serialize(context, entry.getKey(), keyAndValueType[0]);
- serializeAsArray |= key.isJsonObject() || key.isJsonArray();
- keysAndValues.add(key);
- keysAndValues.add(serialize(context, entry.getValue(), keyAndValueType[1]));
- }
-
- if (serializeAsArray) {
- JsonArray result = new JsonArray();
- for (int i = 0; i < keysAndValues.size(); i+=2) {
- JsonArray entryArray = new JsonArray();
- entryArray.add(keysAndValues.get(i));
- entryArray.add(keysAndValues.get(i + 1));
- result.add(entryArray);
- }
- return result;
- } else {
- JsonObject result = new JsonObject();
- for (int i = 0; i < keysAndValues.size(); i+=2) {
- result.add(keysAndValues.get(i).getAsString(), keysAndValues.get(i + 1));
- }
- checkSize(src, src.size(), result, result.entrySet().size());
- return result;
- }
- }
-
- private Type[] typeToTypeArguments(Type typeOfT) {
- if (typeOfT instanceof ParameterizedType) {
- Type[] typeArguments = ((ParameterizedType) typeOfT).getActualTypeArguments();
- if (typeArguments.length != 2) {
- throw new IllegalArgumentException("MapAsArrayTypeAdapter cannot handle " + typeOfT);
- }
- return typeArguments;
- }
- return new Type[] { Object.class, Object.class };
- }
-
- private void checkSize(Object input, int inputSize, Object output, int outputSize) {
- if (inputSize != outputSize) {
- throw new JsonSyntaxException("Input size " + inputSize + " != output size " + outputSize
- + " for input " + input + " and output " + output);
- }
+ // TODO
+ throw new UnsupportedOperationException();
}
}
diff --git a/gson/src/main/java/com/google/gson/MapTypeAdapter.java b/gson/src/main/java/com/google/gson/MapTypeAdapter.java
deleted file mode 100644
index 7f95ef5b..00000000
--- a/gson/src/main/java/com/google/gson/MapTypeAdapter.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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;
-
-import com.google.gson.internal.$Gson$Types;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Default serialization and deserialization of a map type. This implementation really only works
- * well with simple primitive types as the map key. If the key is not a simple primitive then the
- * object is {@code toString}ed and that value is used as its key.
- *
- * @author Joel Leitch
- */
-@SuppressWarnings("unchecked")
-final class MapTypeAdapter extends BaseMapTypeAdapter {
-
- public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
- JsonObject map = new JsonObject();
- Type childGenericType = null;
- if (typeOfSrc instanceof ParameterizedType) {
- Class> rawTypeOfSrc = $Gson$Types.getRawType(typeOfSrc);
- childGenericType = $Gson$Types.getMapKeyAndValueTypes(typeOfSrc, rawTypeOfSrc)[1];
- }
-
- for (Map.Entry entry : (Set) src.entrySet()) {
- Object value = entry.getValue();
-
- JsonElement valueElement;
- if (value == null) {
- valueElement = JsonNull.INSTANCE;
- } else {
- Type childType = (childGenericType == null)
- ? value.getClass() : childGenericType;
- valueElement = serialize(context, value, childType);
- }
- map.add(String.valueOf(entry.getKey()), valueElement);
- }
- return map;
- }
-
- public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
- // Use ObjectConstructor to create instance instead of hard-coding a specific type.
- // This handles cases where users are using their own subclass of Map.
- Map map = constructMapType(typeOfT, context);
- Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT));
- for (Map.Entry entry : json.getAsJsonObject().entrySet()) {
- Object key = context.deserialize(new JsonPrimitive(entry.getKey()), keyAndValueTypes[0]);
- Object value = context.deserialize(entry.getValue(), keyAndValueTypes[1]);
- map.put(key, value);
- }
- return map;
- }
-
- @Override
- public String toString() {
- return MapTypeAdapter.class.getSimpleName();
- }
-}
\ No newline at end of file
diff --git a/gson/src/main/java/com/google/gson/MappedObjectConstructor.java b/gson/src/main/java/com/google/gson/MappedObjectConstructor.java
deleted file mode 100644
index cc2f75bd..00000000
--- a/gson/src/main/java/com/google/gson/MappedObjectConstructor.java
+++ /dev/null
@@ -1,78 +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 com.google.gson.internal.$Gson$Types;
-
-import com.google.gson.internal.UnsafeAllocator;
-import java.lang.reflect.Array;
-import java.lang.reflect.Type;
-
-/**
- * This class contains a mapping of all the application specific
- * {@link InstanceCreator} instances. Registering an {@link InstanceCreator}
- * with this class will override the default object creation that is defined
- * by the ObjectConstructor that this class is wrapping. Using this class
- * with the JSON framework provides the application with "pluggable" modules
- * to customize framework to suit the application's needs.
- *
- * @author Joel Leitch
- */
-final class MappedObjectConstructor implements ObjectConstructor {
- private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
- private static final DefaultConstructorAllocator defaultConstructorAllocator =
- new DefaultConstructorAllocator(500);
-
- private final ParameterizedTypeHandlerMap> instanceCreatorMap;
-
- public MappedObjectConstructor(
- ParameterizedTypeHandlerMap> instanceCreators) {
- instanceCreatorMap = instanceCreators;
- }
-
- @SuppressWarnings("unchecked")
- public T construct(Type typeOfT) {
- InstanceCreator creator = (InstanceCreator) instanceCreatorMap.getHandlerFor(typeOfT, false);
- if (creator != null) {
- return creator.createInstance(typeOfT);
- }
- return (T) constructWithAllocators(typeOfT);
- }
-
- public Object constructArray(Type type, int length) {
- return Array.newInstance($Gson$Types.getRawType(type), length);
- }
-
- @SuppressWarnings({"unchecked", "cast"})
- private T constructWithAllocators(Type typeOfT) {
- try {
- Class clazz = (Class) $Gson$Types.getRawType(typeOfT);
- T obj = defaultConstructorAllocator.newInstance(clazz);
- return (obj == null)
- ? unsafeAllocator.newInstance(clazz)
- : obj;
- } catch (Exception e) {
- throw new RuntimeException(("Unable to invoke no-args constructor for " + typeOfT + ". "
- + "Register an InstanceCreator with Gson for this type may fix this problem."), e);
- }
- }
-
- @Override
- public String toString() {
- return instanceCreatorMap.toString();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/MemoryRefStack.java b/gson/src/main/java/com/google/gson/MemoryRefStack.java
deleted file mode 100644
index 3fbd8463..00000000
--- a/gson/src/main/java/com/google/gson/MemoryRefStack.java
+++ /dev/null
@@ -1,88 +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 com.google.gson.internal.$Gson$Preconditions;
-
-import java.util.Stack;
-
-/**
- * A stack data structure that only does a memory reference comparison
- * when looking for a particular item in the stack. This stack does
- * not allow {@code null} values to be added.
- *
- * @author Joel Leitch
- */
-final class MemoryRefStack {
- private final Stack stack = new Stack();
-
- /**
- * Adds a new element to the top of the stack.
- *
- * @param obj the object to add to the stack
- * @return the object that was added
- */
- public ObjectTypePair push(ObjectTypePair obj) {
- $Gson$Preconditions.checkNotNull(obj);
- return stack.push(obj);
- }
-
- /**
- * Removes the top element from the stack.
- *
- * @return the element being removed from the stack
- * @throws java.util.EmptyStackException thrown if the stack is empty
- */
- public ObjectTypePair pop() {
- return stack.pop();
- }
-
- public boolean isEmpty() {
- return stack.isEmpty();
- }
-
- /**
- * Retrieves the item from the top of the stack, but does not remove it.
- *
- * @return the item from the top of the stack
- * @throws java.util.EmptyStackException thrown if the stack is empty
- */
- public ObjectTypePair peek() {
- return stack.peek();
- }
-
- /**
- * Performs a memory reference check to see it the {@code obj} exists in
- * the stack.
- *
- * @param obj the object to search for in the stack
- * @return true if this object is already in the stack otherwise false
- */
- public boolean contains(ObjectTypePair obj) {
- if (obj == null) {
- return false;
- }
-
- for (ObjectTypePair stackObject : stack) {
- if (stackObject.getObject() == obj.getObject()
- && stackObject.type.equals(obj.type) ) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/NullExclusionStrategy.java b/gson/src/main/java/com/google/gson/NullExclusionStrategy.java
deleted file mode 100644
index b1de1253..00000000
--- a/gson/src/main/java/com/google/gson/NullExclusionStrategy.java
+++ /dev/null
@@ -1,36 +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 acts as a "Null Object" pattern for the {@link ExclusionStrategy}.
- * Passing an instance of this class into the {@link ObjectNavigator} will
- * make the {@link ObjectNavigator} parse/visit every field of the object
- * being navigated.
- *
- * @author Joel Leitch
- */
-final class NullExclusionStrategy implements ExclusionStrategy {
-
- public boolean shouldSkipField(FieldAttributes f) {
- return false;
- }
-
- public boolean shouldSkipClass(Class> clazz) {
- return false;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/ObjectNavigator.java b/gson/src/main/java/com/google/gson/ObjectNavigator.java
deleted file mode 100644
index 860cc25e..00000000
--- a/gson/src/main/java/com/google/gson/ObjectNavigator.java
+++ /dev/null
@@ -1,134 +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 com.google.gson.internal.$Gson$Types;
-
-import java.lang.reflect.Type;
-
-/**
- * Provides ability to apply a visitor to an object and all of its fields
- * recursively.
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- */
-final class ObjectNavigator {
-
- public interface Visitor {
- public void start(ObjectTypePair node);
-
- public void end(ObjectTypePair node);
-
- /**
- * This is called before the object navigator starts visiting the current
- * object
- */
- void startVisitingObject(Object node);
-
- /**
- * This is called to visit the current object if it is an array
- */
- void visitArray(Object array, Type componentType);
-
- /**
- * This is called to visit an object field of the current object
- */
- void visitObjectField(FieldAttributes f, Type typeOfF, Object obj);
-
- /**
- * This is called to visit an array field of the current object
- */
- void visitArrayField(FieldAttributes f, Type typeOfF, Object obj);
-
- /**
- * This is called to visit an object using a custom handler
- *
- * @return true if a custom handler exists, false otherwise
- */
- public boolean visitUsingCustomHandler(ObjectTypePair objTypePair);
-
- /**
- * This is called to visit a field of the current object using a custom
- * handler
- */
- public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField,
- Object parent);
-
- void visitPrimitive(Object primitive);
-
- /**
- * Retrieve the current target
- */
- Object getTarget();
- }
-
- private final ExclusionStrategy exclusionStrategy;
- private final ReflectingFieldNavigator reflectingFieldNavigator;
-
- /**
- * @param strategy the concrete exclusion strategy object to be used to filter out fields of an
- * object.
- */
- ObjectNavigator(ExclusionStrategy strategy) {
- this.exclusionStrategy = strategy == null ? new NullExclusionStrategy() : strategy;
- this.reflectingFieldNavigator = new ReflectingFieldNavigator(exclusionStrategy);
- }
-
- /**
- * Navigate all the fields of the specified object. If a field is null, it
- * does not get visited.
- * @param objTypePair The object,type (fully genericized) being navigated
- */
- public void accept(ObjectTypePair objTypePair, Visitor visitor) {
- if (exclusionStrategy.shouldSkipClass($Gson$Types.getRawType(objTypePair.type))) {
- return;
- }
- boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
- if (!visitedWithCustomHandler) {
- objTypePair = objTypePair.toMoreSpecificType();
- Object obj = objTypePair.getObject();
- Object objectToVisit = (obj == null) ? visitor.getTarget() : obj;
- if (objectToVisit == null) {
- return;
- }
- objTypePair.setObject(objectToVisit);
- visitor.start(objTypePair);
- try {
- if ($Gson$Types.isArray(objTypePair.getMoreSpecificType())) {
- visitor.visitArray(objectToVisit, objTypePair.type);
- } else if (objTypePair.type == Object.class && isPrimitiveOrString(objectToVisit)) {
- // TODO(Joel): this is only used for deserialization of "primitives"
- // we should rethink this!!!
- visitor.visitPrimitive(objectToVisit);
- visitor.getTarget();
- } else {
- visitor.startVisitingObject(objectToVisit);
- reflectingFieldNavigator.visitFieldsReflectively(objTypePair, visitor);
- }
- } finally {
- visitor.end(objTypePair);
- }
- }
- }
-
- private static boolean isPrimitiveOrString(Object objectToVisit) {
- Class> realClazz = objectToVisit.getClass();
- return realClazz == Object.class || realClazz == String.class
- || Primitives.unwrap(realClazz).isPrimitive();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/ObjectTypePair.java b/gson/src/main/java/com/google/gson/ObjectTypePair.java
deleted file mode 100644
index 3e85eae7..00000000
--- a/gson/src/main/java/com/google/gson/ObjectTypePair.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2009 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;
-
-/**
- * A holder class for an object and its type
- *
- * @author Inderjeet Singh
- */
-final class ObjectTypePair {
- private Object obj;
- final Type type;
- private final boolean preserveType;
- private final boolean systemOnly;
-
- ObjectTypePair(Object obj, Type type, boolean preserveType, boolean systemOnly) {
- this.obj = obj;
- this.type = type;
- this.preserveType = preserveType;
- this.systemOnly = systemOnly;
- }
-
- Object getObject() {
- return obj;
- }
-
- void setObject(Object obj) {
- this.obj = obj;
- }
-
- Type getType() {
- return type;
- }
-
- @Override
- public String toString() {
- return String.format("preserveType: %b, type: %s, obj: %s", preserveType, type, obj);
- }
-
- Pair getMatchingHandler(
- ParameterizedTypeHandlerMap handlers) {
- HANDLER handler = null;
- if (!preserveType && obj != null) {
- // First try looking up the handler for the actual type
- ObjectTypePair moreSpecificType = toMoreSpecificType();
- handler = handlers.getHandlerFor(moreSpecificType.type, systemOnly);
- if (handler != null) {
- return new Pair(handler, moreSpecificType);
- }
- }
- // Try the specified type
- handler = handlers.getHandlerFor(type, systemOnly);
- return handler == null ? null : new Pair(handler, this);
- }
-
- ObjectTypePair toMoreSpecificType() {
- if (preserveType || obj == null) {
- return this;
- }
- Type actualType = getActualTypeIfMoreSpecific(type, obj.getClass());
- if (actualType == type) {
- return this;
- }
- return new ObjectTypePair(obj, actualType, true, systemOnly);
- }
-
- Type getMoreSpecificType() {
- if (preserveType || obj == null) {
- return type;
- }
- return getActualTypeIfMoreSpecific(type, obj.getClass());
- }
-
- // This takes care of situations where the field was declared as an Object, but the
- // actual value contains something more specific. See Issue 54.
- // TODO (inder): This solution will not work if the field is of a generic type, but
- // the actual object is of a raw type (which is a sub-class of the generic type).
- static Type getActualTypeIfMoreSpecific(Type type, Class> actualClass) {
- if (type instanceof Class>) {
- Class> typeAsClass = (Class>) type;
- if (typeAsClass.isAssignableFrom(actualClass)) {
- type = actualClass;
- }
- if (type == Object.class) {
- type = actualClass;
- }
- }
- return type;
- }
-
- @Override
- public int hashCode() {
- // Not using type.hashCode() since I am not sure if the subclasses of type reimplement
- // hashCode() to be equal for equal types
- return ((obj == null) ? 31 : obj.hashCode());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- ObjectTypePair other = (ObjectTypePair) obj;
- if (this.obj == null) {
- if (other.obj != null) {
- return false;
- }
- } else if (this.obj != other.obj) { // Checking for reference equality
- return false;
- }
- if (type == null) {
- if (other.type != null) {
- return false;
- }
- } else if (!type.equals(other.type)) {
- return false;
- }
- return preserveType == other.preserveType && systemOnly == other.systemOnly;
- }
-
- public boolean isPreserveType() {
- return preserveType;
- }
-
- public boolean isSystemOnly() {
- return systemOnly;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/ReflectingFieldNavigator.java b/gson/src/main/java/com/google/gson/ReflectingFieldNavigator.java
deleted file mode 100644
index 863fc790..00000000
--- a/gson/src/main/java/com/google/gson/ReflectingFieldNavigator.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.google.gson.ObjectNavigator.Visitor;
-import com.google.gson.internal.$Gson$Preconditions;
-import com.google.gson.internal.$Gson$Types;
-
-/**
- * Visits each of the fields of the specified class using reflection
- *
- * @author Inderjeet Singh
- * @author Joel Leitch
- * @author Jesse Wilson
- */
-final class ReflectingFieldNavigator {
-
- private static final Cache> fieldsCache =
- new LruCache>(500);
-
- private final ExclusionStrategy exclusionStrategy;
-
- /**
- * @param exclusionStrategy the concrete strategy object to be used to filter out fields of an
- * object.
- */
- ReflectingFieldNavigator(ExclusionStrategy exclusionStrategy) {
- this.exclusionStrategy = $Gson$Preconditions.checkNotNull(exclusionStrategy);
- }
-
- /**
- * @param objTypePair The object,type (fully genericized) being navigated
- * @param visitor the visitor to visit each field with
- */
- void visitFieldsReflectively(ObjectTypePair objTypePair, Visitor visitor) {
- Type moreSpecificType = objTypePair.getMoreSpecificType();
- Object obj = objTypePair.getObject();
- for (FieldAttributes fieldAttributes : getAllFields(moreSpecificType, objTypePair.getType())) {
- if (exclusionStrategy.shouldSkipField(fieldAttributes)
- || exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
- continue; // skip
- }
- Type resolvedTypeOfField = getMoreSpecificType(fieldAttributes.getResolvedType(), obj, fieldAttributes);
- boolean visitedWithCustomHandler =
- visitor.visitFieldUsingCustomHandler(fieldAttributes, resolvedTypeOfField, obj);
- if (!visitedWithCustomHandler) {
- if ($Gson$Types.isArray(resolvedTypeOfField)) {
- visitor.visitArrayField(fieldAttributes, resolvedTypeOfField, obj);
- } else {
- visitor.visitObjectField(fieldAttributes, resolvedTypeOfField, obj);
- }
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- private static Type getMoreSpecificType(Type type, Object obj, FieldAttributes fieldAttributes) {
- try {
- if (obj != null && (Object.class == type || type instanceof TypeVariable)) {
- Object fieldValue = fieldAttributes.get(obj);
- if (fieldValue != null) {
- type = fieldValue.getClass();
- }
- }
- } catch (IllegalAccessException e) {
- }
- return type;
- }
-
- private List getAllFields(Type type, Type declaredType) {
- List fields = fieldsCache.getElement(type);
- if (fields == null) {
- fields = new ArrayList();
- for (Class> curr : getInheritanceHierarchy(type)) {
- Field[] currentClazzFields = curr.getDeclaredFields();
- AccessibleObject.setAccessible(currentClazzFields, true);
- Field[] classFields = currentClazzFields;
- for (Field f : classFields) {
- fields.add(new FieldAttributes(curr, f, declaredType));
- }
- }
- fieldsCache.addElement(type, fields);
- }
- return fields;
- }
-
- /**
- * Returns a list of classes corresponding to the inheritance of specified type
- */
- private List> getInheritanceHierarchy(Type type) {
- List> classes = new ArrayList>();
- Class> topLevelClass = $Gson$Types.getRawType(type);
- for (Class> curr = topLevelClass; curr != null && !curr.equals(Object.class); curr =
- curr.getSuperclass()) {
- if (!curr.isSynthetic()) {
- classes.add(curr);
- }
- }
- return classes;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java
new file mode 100644
index 00000000..b3c6db33
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java
@@ -0,0 +1,173 @@
+/*
+ * 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.internal;
+
+import com.google.gson.InstanceCreator;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Returns a function that can construct an instance of a requested type.
+ */
+public final class ConstructorConstructor {
+ private final ParameterizedTypeHandlerMap> instanceCreators;
+
+ public ConstructorConstructor(ParameterizedTypeHandlerMap> instanceCreators) {
+ this.instanceCreators = instanceCreators;
+ }
+
+ public ConstructorConstructor() {
+ this(new ParameterizedTypeHandlerMap>());
+ }
+
+ public ObjectConstructor getConstructor(TypeToken typeToken) {
+ final Type type = typeToken.getType();
+ final Class super T> rawType = typeToken.getRawType();
+
+ // first try an instance creator
+
+ @SuppressWarnings("unchecked") // types must agree
+ final InstanceCreator creator
+ = (InstanceCreator) instanceCreators.getHandlerFor(type, false);
+ if (creator != null) {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return creator.createInstance(type);
+ }
+ };
+ }
+
+ ObjectConstructor defaultConstructor = newDefaultConstructor(rawType);
+ if (defaultConstructor != null) {
+ return defaultConstructor;
+ }
+
+ ObjectConstructor defaultImplementation = newDefaultImplementationConstructor(rawType);
+ if (defaultImplementation != null) {
+ return defaultImplementation;
+ }
+
+ // finally try unsafe
+ return newUnsafeAllocator(type, rawType);
+ }
+
+ private ObjectConstructor newDefaultConstructor(Class super T> rawType) {
+ try {
+ final Constructor super T> constructor = rawType.getDeclaredConstructor();
+ if (!constructor.isAccessible()) {
+ constructor.setAccessible(true);
+ }
+ return new ObjectConstructor() {
+ @SuppressWarnings("unchecked") // T is the same raw type as is requested
+ @Override public T construct() {
+ try {
+ Object[] args = null;
+ return (T) constructor.newInstance(args);
+ } catch (InstantiationException e) {
+ // TODO: JsonParseException ?
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ // TODO: don't wrap if cause is unchecked!
+ // TODO: JsonParseException ?
+ throw new RuntimeException(e.getTargetException());
+ } catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ }
+ };
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Constructors for common interface types like Map and List and their
+ * subytpes.
+ */
+ @SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is
+ private ObjectConstructor newDefaultImplementationConstructor(Class super T> rawType) {
+ if (Collection.class.isAssignableFrom(rawType)) {
+ if (SortedSet.class.isAssignableFrom(rawType)) {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return (T) new TreeSet();
+ }
+ };
+ } else if (Set.class.isAssignableFrom(rawType)) {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return (T) new LinkedHashSet();
+ }
+ };
+ } else if (Queue.class.isAssignableFrom(rawType)) {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return (T) new LinkedList();
+ }
+ };
+ } else {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return (T) new ArrayList();
+ }
+ };
+ }
+ }
+
+ if (Map.class.isAssignableFrom(rawType)) {
+ return new ObjectConstructor() {
+ @Override public T construct() {
+ return (T) new LinkedHashMap();
+ }
+ };
+ // TODO: SortedMap ?
+ }
+
+ return null;
+ }
+
+ private ObjectConstructor newUnsafeAllocator(
+ final Type type, final Class super T> rawType) {
+ return new ObjectConstructor() {
+ private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
+ @Override public T construct() {
+ try {
+ return (T) unsafeAllocator.newInstance(rawType);
+ } catch (Exception e) {
+ throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "
+ + "Register an InstanceCreator with Gson for this type may fix this problem."), e);
+ }
+ }
+ };
+ }
+
+ @Override public String toString() {
+ return instanceCreators.toString();
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/ObjectConstructor.java b/gson/src/main/java/com/google/gson/internal/ObjectConstructor.java
similarity index 60%
rename from gson/src/main/java/com/google/gson/ObjectConstructor.java
rename to gson/src/main/java/com/google/gson/internal/ObjectConstructor.java
index 67973e9f..6ef20607 100644
--- a/gson/src/main/java/com/google/gson/ObjectConstructor.java
+++ b/gson/src/main/java/com/google/gson/internal/ObjectConstructor.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.google.gson;
-
-import java.lang.reflect.Type;
+package com.google.gson.internal;
/**
* Defines a generic object construction factory. The purpose of this class
@@ -26,22 +24,10 @@ import java.lang.reflect.Type;
* @author Inderjeet Singh
* @author Joel Leitch
*/
-interface ObjectConstructor {
+public interface ObjectConstructor {
/**
- * Creates a new instance of the given type.
- *
- * @param typeOfT the class type that should be instantiated
- * @return a default instance of the provided class.
+ * Returns a new instance.
*/
- public T construct(Type typeOfT);
-
- /**
- * Constructs an array type of the provided length.
- *
- * @param typeOfArrayElements type of objects in the array
- * @param length size of the array
- * @return new array of size length
- */
- public Object constructArray(Type typeOfArrayElements, int length);
+ public T construct();
}
\ No newline at end of file
diff --git a/gson/src/main/java/com/google/gson/Pair.java b/gson/src/main/java/com/google/gson/internal/Pair.java
similarity index 95%
rename from gson/src/main/java/com/google/gson/Pair.java
rename to gson/src/main/java/com/google/gson/internal/Pair.java
index ce5496f1..205ae295 100644
--- a/gson/src/main/java/com/google/gson/Pair.java
+++ b/gson/src/main/java/com/google/gson/internal/Pair.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.google.gson;
+package com.google.gson.internal;
/**
* A simple object that holds onto a pair of object references, first and second.
@@ -25,7 +25,7 @@ package com.google.gson;
* @param
* @param
*/
-final class Pair {
+public final class Pair {
public final FIRST first;
public final SECOND second;
diff --git a/gson/src/main/java/com/google/gson/ParameterizedTypeHandlerMap.java b/gson/src/main/java/com/google/gson/internal/ParameterizedTypeHandlerMap.java
similarity index 98%
rename from gson/src/main/java/com/google/gson/ParameterizedTypeHandlerMap.java
rename to gson/src/main/java/com/google/gson/internal/ParameterizedTypeHandlerMap.java
index 7add6ad4..0bb27447 100644
--- a/gson/src/main/java/com/google/gson/ParameterizedTypeHandlerMap.java
+++ b/gson/src/main/java/com/google/gson/internal/ParameterizedTypeHandlerMap.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.google.gson;
-
-import com.google.gson.internal.$Gson$Types;
+package com.google.gson.internal;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -35,7 +33,7 @@ import java.util.logging.Logger;
*
* @param The handler that will be looked up by type
*/
-final class ParameterizedTypeHandlerMap {
+public final class ParameterizedTypeHandlerMap {
private static final Logger logger =
Logger.getLogger(ParameterizedTypeHandlerMap.class.getName());
/**
@@ -222,7 +220,7 @@ final class ParameterizedTypeHandlerMap {
ParameterizedTypeHandlerMap copy = new ParameterizedTypeHandlerMap();
// Instead of individually registering entries in the map, make an efficient copy
// of the list and map
-
+
// TODO (inder): Performance optimization. We can probably just share the
// systemMap and systemTypeHierarchyList instead of making copies
copy.systemMap.putAll(systemMap);
diff --git a/gson/src/main/java/com/google/gson/Primitives.java b/gson/src/main/java/com/google/gson/internal/Primitives.java
similarity index 98%
rename from gson/src/main/java/com/google/gson/Primitives.java
rename to gson/src/main/java/com/google/gson/internal/Primitives.java
index 446890d4..c9285470 100644
--- a/gson/src/main/java/com/google/gson/Primitives.java
+++ b/gson/src/main/java/com/google/gson/internal/Primitives.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.google.gson;
+package com.google.gson.internal;
import com.google.gson.internal.$Gson$Preconditions;
@@ -29,7 +29,7 @@ import java.util.Map;
*
* @author Kevin Bourrillion
*/
-final class Primitives {
+public final class Primitives {
private Primitives() {}
/** A map from primitive types to their corresponding wrapper types. */
diff --git a/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java
index 30ea9ea7..8d6fb881 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java
@@ -28,7 +28,7 @@ import java.math.BigDecimal;
*
* @author Joel Leitch
*/
-public class BigDecimalTypeAdapter extends TypeAdapter {
+public final class BigDecimalTypeAdapter extends TypeAdapter {
@Override
public BigDecimal read(JsonReader reader) throws IOException {
diff --git a/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java
index 9e0bfd98..f103ae8a 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java
@@ -28,7 +28,7 @@ import java.math.BigInteger;
*
* @author Joel Leitch
*/
-public class BigIntegerTypeAdapter extends TypeAdapter {
+public final class BigIntegerTypeAdapter extends TypeAdapter {
@Override
public BigInteger read(JsonReader reader) throws IOException {
diff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapter.java
deleted file mode 100644
index 01747b51..00000000
--- a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapter.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.internal.bind;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import com.google.gson.internal.$Gson$Types;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-
-/**
- * Adapt a homogeneous collection of objects.
- */
-public final class CollectionTypeAdapter extends TypeAdapter> {
- public static final Factory FACTORY = new Factory() {
- public TypeAdapter create(MiniGson context, TypeToken typeToken) {
- Type type = typeToken.getType();
-
- Class super T> rawType = typeToken.getRawType();
- if (!Collection.class.isAssignableFrom(rawType)) {
- return null;
- }
-
- Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
- TypeAdapter> elementTypeAdapter = context.getAdapter(TypeToken.get(elementType));
-
- Class> constructorType;
-
- if (rawType == List.class || rawType == Collection.class) {
- constructorType = ArrayList.class;
- } else if (rawType == Set.class) {
- constructorType = LinkedHashSet.class;
- } else if (rawType == Queue.class) {
- constructorType = LinkedList.class;
- } else if (rawType == SortedSet.class) {
- constructorType = TreeSet.class;
- } else {
- constructorType = rawType;
- }
-
- Constructor> constructor = null;
- try {
- constructor = constructorType.getConstructor();
- } catch (NoSuchMethodException ignored) {
- }
-
- @SuppressWarnings("unchecked") // create() doesn't define a type parameter
- TypeAdapter result = new CollectionTypeAdapter(context, elementType, elementTypeAdapter, constructor);
- return result;
- }
- };
-
- private final TypeAdapter elementTypeAdapter;
- private final Constructor extends Collection> constructor;
-
- public CollectionTypeAdapter(MiniGson context, Type elementType, TypeAdapter elementTypeAdapter,
- Constructor extends Collection> constructor) {
- this.elementTypeAdapter =
- new TypeAdapterRuntimeTypeWrapper(context, elementTypeAdapter, elementType);
- this.constructor = constructor;
- }
-
- public Collection read(JsonReader reader) throws IOException {
- if (reader.peek() == JsonToken.NULL) {
- reader.nextNull(); // TODO: does this belong here?
- return null;
- }
-
- if (constructor == null) {
- throw new UnsupportedOperationException("TODO: use unsafeAllocator.newInstance");
- }
- Collection collection = Reflection.newInstance(constructor);
- reader.beginArray();
- while (reader.hasNext()) {
- E instance = elementTypeAdapter.read(reader);
- collection.add(instance);
- }
- reader.endArray();
- return collection;
- }
-
- public void write(JsonWriter writer, Collection collection) throws IOException {
- if (collection == null) {
- writer.nullValue(); // TODO: better policy here?
- return;
- }
-
- writer.beginArray();
- for (E element : collection) {
- elementTypeAdapter.write(writer, element);
- }
- writer.endArray();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java
new file mode 100644
index 00000000..84871cf6
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java
@@ -0,0 +1,98 @@
+/*
+ * 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.internal.bind;
+
+import com.google.gson.internal.$Gson$Types;
+import com.google.gson.internal.ConstructorConstructor;
+import com.google.gson.internal.ObjectConstructor;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * Adapt a homogeneous collection of objects.
+ */
+public final class CollectionTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ConstructorConstructor constructorConstructor;
+
+ public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
+ this.constructorConstructor = constructorConstructor;
+ }
+
+ public TypeAdapter create(MiniGson context, TypeToken typeToken) {
+ Type type = typeToken.getType();
+
+ Class super T> rawType = typeToken.getRawType();
+ if (!Collection.class.isAssignableFrom(rawType)) {
+ return null;
+ }
+
+ Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
+ TypeAdapter> elementTypeAdapter = context.getAdapter(TypeToken.get(elementType));
+ ObjectConstructor constructor = constructorConstructor.getConstructor(typeToken);
+
+ @SuppressWarnings("unchecked") // create() doesn't define a type parameter
+ TypeAdapter result = new Adapter(context, elementType, elementTypeAdapter, constructor);
+ return result;
+ }
+
+ private final class Adapter extends TypeAdapter> {
+ private final TypeAdapter elementTypeAdapter;
+ private final ObjectConstructor extends Collection> constructor;
+
+ public Adapter(MiniGson context, Type elementType,
+ TypeAdapter elementTypeAdapter,
+ ObjectConstructor extends Collection> constructor) {
+ this.elementTypeAdapter =
+ new TypeAdapterRuntimeTypeWrapper(context, elementTypeAdapter, elementType);
+ this.constructor = constructor;
+ }
+
+ public Collection read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
+
+ Collection collection = constructor.construct();
+ reader.beginArray();
+ while (reader.hasNext()) {
+ E instance = elementTypeAdapter.read(reader);
+ collection.add(instance);
+ }
+ reader.endArray();
+ return collection;
+ }
+
+ public void write(JsonWriter writer, Collection collection) throws IOException {
+ if (collection == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+
+ writer.beginArray();
+ for (E element : collection) {
+ elementTypeAdapter.write(writer, element);
+ }
+ writer.endArray();
+ }
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ExcludedTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ExcludedTypeAdapterFactory.java
new file mode 100644
index 00000000..1e253556
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/bind/ExcludedTypeAdapterFactory.java
@@ -0,0 +1,79 @@
+/*
+ * 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.internal.bind;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+
+/**
+ * This type adapter skips values using an exclusion strategy. It may delegate
+ * to another type adapter if only one direction is excluded.
+ */
+public final class ExcludedTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ExclusionStrategy serializationExclusionStrategy;
+ private final ExclusionStrategy deserializationExclusionStrategy;
+
+ public ExcludedTypeAdapterFactory(ExclusionStrategy serializationExclusionStrategy,
+ ExclusionStrategy deserializationExclusionStrategy) {
+ this.serializationExclusionStrategy = serializationExclusionStrategy;
+ this.deserializationExclusionStrategy = deserializationExclusionStrategy;
+ }
+
+ public TypeAdapter create(final MiniGson context, final TypeToken type) {
+ Class> rawType = type.getRawType();
+ final boolean skipSerialize = serializationExclusionStrategy.shouldSkipClass(rawType);
+ final boolean skipDeserialize = deserializationExclusionStrategy.shouldSkipClass(rawType);
+
+ if (!skipSerialize && !skipDeserialize) {
+ return null;
+ }
+
+ return new TypeAdapter() {
+ /**
+ * The delegate is lazily created because it may not be needed, and
+ * creating it may fail.
+ */
+ private TypeAdapter delegate;
+
+ @Override public T read(JsonReader reader) throws IOException {
+ if (skipDeserialize) {
+ reader.skipValue();
+ return null;
+ }
+ return delegate().read(reader);
+ }
+
+ @Override public void write(JsonWriter writer, T value) throws IOException {
+ if (skipSerialize) {
+ writer.nullValue();
+ return;
+ }
+ delegate().write(writer, value);
+ }
+
+ private TypeAdapter delegate() {
+ TypeAdapter d = delegate;
+ return d != null
+ ? d
+ : (delegate = context.getNextAdapter(ExcludedTypeAdapterFactory.this, type));
+ }
+ };
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/GsonCompatibleMapTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/GsonCompatibleMapTypeAdapter.java
deleted file mode 100644
index f0567380..00000000
--- a/gson/src/main/java/com/google/gson/internal/bind/GsonCompatibleMapTypeAdapter.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.internal.bind;
-
-import com.google.gson.internal.$Gson$Types;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Adapt a map whose keys are any type.
- */
-public final class GsonCompatibleMapTypeAdapter extends TypeAdapter> {
- public static final Factory FACTORY = new Factory() {
- public TypeAdapter create(MiniGson context, TypeToken typeToken) {
- Type type = typeToken.getType();
-
- Class super T> rawType = typeToken.getRawType();
- if (!Map.class.isAssignableFrom(rawType)) {
- return null;
- }
-
- Type childGenericType = Object.class;
- if (type instanceof ParameterizedType) {
- Class> rawTypeOfSrc = $Gson$Types.getRawType(type);
- childGenericType = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc)[1];
- }
- TypeAdapter valueAdapter = context.getAdapter(TypeToken.get(childGenericType));
-
- Constructor> constructor;
- try {
- Class> constructorType = (rawType == Map.class) ? LinkedHashMap.class : rawType;
- constructor = constructorType.getConstructor();
- } catch (NoSuchMethodException e) {
- return null;
- }
-
- @SuppressWarnings("unchecked") // we don't define a type parameter for the key or value types
- TypeAdapter result = new GsonCompatibleMapTypeAdapter(valueAdapter, constructor);
- return result;
- }
- };
-
- private final TypeAdapter valueTypeAdapter;
- private final Constructor extends Map> constructor;
-
- public GsonCompatibleMapTypeAdapter(TypeAdapter valueTypeAdapter,
- Constructor extends Map> constructor) {
- this.valueTypeAdapter = valueTypeAdapter;
- this.constructor = constructor;
- }
-
- public Map, V> read(JsonReader reader) throws IOException {
- if (reader.peek() == JsonToken.NULL) {
- reader.nextNull(); // TODO: does this belong here?
- return null;
- }
-
- Map map = Reflection.newInstance(constructor);
- reader.beginObject();
- while (reader.hasNext()) {
- String key = reader.nextName();
- V value = valueTypeAdapter.read(reader);
- map.put(key, value); // TODO: convert to the map's key type?
- }
- reader.endObject();
- return map;
- }
-
- public void write(JsonWriter writer, Map, V> map) throws IOException {
- if (map == null) {
- writer.nullValue(); // TODO: better policy here?
- return;
- }
-
- writer.beginObject();
- for (Map.Entry, V> entry : map.entrySet()) {
- String key = String.valueOf(entry.getKey());
- writer.name(key);
- valueTypeAdapter.write(writer, entry.getValue());
- }
- writer.endObject();
- }
-}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
new file mode 100644
index 00000000..c8e6c664
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
@@ -0,0 +1,101 @@
+/*
+ * 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.internal.bind;
+
+import com.google.gson.internal.$Gson$Types;
+import com.google.gson.internal.ConstructorConstructor;
+import com.google.gson.internal.ObjectConstructor;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+/**
+ * Adapt a map whose keys are any type.
+ */
+public final class MapTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ConstructorConstructor constructorConstructor;
+
+ public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
+ this.constructorConstructor = constructorConstructor;
+ }
+
+ public TypeAdapter create(MiniGson context, TypeToken typeToken) {
+ Type type = typeToken.getType();
+
+ Class super T> rawType = typeToken.getRawType();
+ if (!Map.class.isAssignableFrom(rawType)) {
+ return null;
+ }
+
+ Class> rawTypeOfSrc = $Gson$Types.getRawType(type);
+ Type childGenericType = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc)[1];
+ TypeAdapter valueAdapter = context.getAdapter(TypeToken.get(childGenericType));
+ ObjectConstructor constructor = constructorConstructor.getConstructor(typeToken);
+
+ @SuppressWarnings("unchecked") // we don't define a type parameter for the key or value types
+ TypeAdapter result = new Adapter(valueAdapter, constructor);
+ return result;
+ }
+
+ private final class Adapter extends TypeAdapter> {
+ private final TypeAdapter valueTypeAdapter;
+ private final ObjectConstructor extends Map> constructor;
+
+ public Adapter(TypeAdapter valueTypeAdapter,
+ ObjectConstructor extends Map> constructor) {
+ this.valueTypeAdapter = valueTypeAdapter;
+ this.constructor = constructor;
+ }
+
+ public Map, V> read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
+
+ Map map = constructor.construct();
+
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String key = reader.nextName();
+ V value = valueTypeAdapter.read(reader);
+ map.put(key, value); // TODO: convert to the map's key type?
+ }
+ reader.endObject();
+ return map;
+ }
+
+ public void write(JsonWriter writer, Map, V> map) throws IOException {
+ if (map == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+
+ writer.beginObject();
+ for (Map.Entry, V> entry : map.entrySet()) {
+ String key = String.valueOf(entry.getKey());
+ writer.name(key);
+ valueTypeAdapter.write(writer, entry.getValue());
+ }
+ writer.endObject();
+ }
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/MiniGson.java b/gson/src/main/java/com/google/gson/internal/bind/MiniGson.java
index 79f7a01b..bb73efc9 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/MiniGson.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/MiniGson.java
@@ -16,6 +16,10 @@
package com.google.gson.internal.bind;
+import com.google.gson.internal.ConstructorConstructor;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -23,10 +27,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
/**
* A basic binding between JSON and Java objects.
*/
@@ -48,6 +48,7 @@ public final class MiniGson {
private final List factories;
private MiniGson(Builder builder) {
+ ConstructorConstructor constructorConstructor = new ConstructorConstructor();
List factories = new ArrayList();
if (builder.addDefaultFactories) {
factories.add(TypeAdapters.BOOLEAN_FACTORY);
@@ -59,11 +60,11 @@ public final class MiniGson {
}
factories.addAll(builder.factories);
if (builder.addDefaultFactories) {
- factories.add(CollectionTypeAdapter.FACTORY);
- factories.add(StringToValueMapTypeAdapter.FACTORY);
+ factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
+ factories.add(new StringToValueMapTypeAdapterFactory(constructorConstructor));
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
- factories.add(ReflectiveTypeAdapter.FACTORY);
+ factories.add(new ReflectiveTypeAdapterFactory(constructorConstructor));
}
this.factories = Collections.unmodifiableList(factories);
}
@@ -100,6 +101,33 @@ public final class MiniGson {
}
}
+ /**
+ * Returns a type adapter for {@code} type that isn't {@code skipPast}. This
+ * can be used for type adapters to compose other, simpler type adapters.
+ *
+ * @throws IllegalArgumentException if this GSON cannot serialize and
+ * deserialize {@code type}.
+ */
+ public TypeAdapter getNextAdapter(TypeAdapter.Factory skipPast, TypeToken type) {
+ boolean skipPastFound = false;
+
+ for (TypeAdapter.Factory factory : factories) {
+ if (!skipPastFound) {
+ if (factory == skipPast) {
+ skipPastFound = true;
+ }
+ continue;
+ }
+
+ TypeAdapter candidate = factory.create(this, type);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+
+ throw new IllegalArgumentException("This MiniGSON cannot serialize " + type);
+ }
+
static class FutureTypeAdapter extends TypeAdapter {
private TypeAdapter delegate;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/Reflection.java b/gson/src/main/java/com/google/gson/internal/bind/Reflection.java
index 77b66eb9..a901ad11 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/Reflection.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/Reflection.java
@@ -15,8 +15,6 @@
*/
package com.google.gson.internal.bind;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -27,29 +25,8 @@ final class Reflection {
public static Type getRuntimeTypeIfMoreSpecific(Type type, Object value) {
if (value != null
&& (type == Object.class || type instanceof TypeVariable || type instanceof Class>)) {
- type = (Class>) value.getClass();
+ type = value.getClass();
}
return type;
}
-
- // TODO: this should use Joel's unsafe constructor stuff
- public static T newInstance(Constructor constructor) {
- if (!constructor.isAccessible()) {
- constructor.setAccessible(true);
- }
- try {
- Object[] args = null;
- return constructor.newInstance(args);
- } catch (InstantiationException e) {
- // TODO: JsonParseException ?
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- // TODO: don't wrap if cause is unchecked!
- // TODO: JsonParseException ?
- throw new RuntimeException(e.getTargetException());
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- }
- }
-
}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java
deleted file mode 100644
index 117c8773..00000000
--- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * 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.internal.bind;
-
-import com.google.gson.JsonSyntaxException;
-import java.io.IOException;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.google.gson.internal.$Gson$Types;
-import com.google.gson.internal.UnsafeAllocator;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-
-/**
- * Adapts the fields of an object to the properties of a JSON object.
- */
-public final class ReflectiveTypeAdapter extends TypeAdapter {
- public static final Factory FACTORY = new FactoryImpl();
-
- private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
- private final Class super T> rawType;
- private final Constructor super T> constructor;
- private final Map map;
- private final BoundField[] boundFields;
-
- ReflectiveTypeAdapter(Class super T> rawType, Constructor super T> constructor, Map map) {
- this.rawType = rawType;
- this.constructor = constructor;
- this.map = map;
- this.boundFields = map.values().toArray(new BoundField[map.size()]);
- }
-
- @SuppressWarnings("unchecked") // the '? super T' is a raw T (the only kind we can construct)
- public T read(JsonReader reader) throws IOException {
- if (reader.peek() == JsonToken.NULL) {
- reader.nextNull(); // TODO: does this belong here?
- return null;
- }
-
- T instance;
- if (constructor != null) {
- instance = (T) Reflection.newInstance(constructor);
- } else {
- try {
- instance = (T) unsafeAllocator.newInstance(rawType);
- } catch (Exception e) {
- throw new RuntimeException(("Unable to invoke no-args constructor for " + rawType.getName()
- + ". Register an InstanceCreator with Gson for this type may fix this problem."), e);
- }
- }
-
- // TODO: null out the other fields?
-
- try {
- reader.beginObject();
- while (reader.hasNext()) {
- String name = reader.nextName();
- BoundField field = map.get(name);
- if (field == null || !field.deserialized) {
- // TODO: define a better policy
- reader.skipValue();
- } else {
- field.read(reader, instance);
- }
- }
- } catch (IllegalStateException e) {
- throw new JsonSyntaxException(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError();
- }
- reader.endObject();
- return instance;
- }
-
- public void write(JsonWriter writer, T value) throws IOException {
- if (value == null) {
- writer.nullValue(); // TODO: better policy here?
- return;
- }
-
- writer.beginObject();
- try {
- for (BoundField boundField : boundFields) {
- if (boundField.serialized) {
- writer.name(boundField.name);
- boundField.write(writer, value);
- }
- }
- } catch (IllegalAccessException e) {
- throw new AssertionError();
- }
- writer.endObject();
- }
-
- static BoundField createBoundField(
- final MiniGson context, final Field field, final String name,
- final TypeToken> fieldType, boolean serialize, boolean deserialize) {
- // special casing primitives here saves ~5% on Android...
- return new BoundField(name, serialize, deserialize) {
- final TypeAdapter> typeAdapter = context.getAdapter(fieldType);
- @SuppressWarnings("unchecked") // the type adapter and field type always agree
- @Override void write(JsonWriter writer, Object value)
- throws IOException, IllegalAccessException {
- Object fieldValue = field.get(value);
- TypeAdapter t =
- new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType());
- t.write(writer, fieldValue);
- }
- @Override void read(JsonReader reader, Object value)
- throws IOException, IllegalAccessException {
- Object fieldValue = typeAdapter.read(reader);
- field.set(value, fieldValue);
- }
- };
- }
-
- public static class FactoryImpl implements Factory {
- public boolean serializeField(Class> declaringClazz, Field f, Type declaredType) {
- return !f.isSynthetic();
- }
- public boolean deserializeField(Class> declaringClazz, Field f, Type declaredType) {
- return !f.isSynthetic();
- }
-
- public String getFieldName(Class> declaringClazz, Field f, Type declaredType) {
- return f.getName();
- }
-
- public TypeAdapter create(MiniGson context, TypeToken type) {
- Class super T> raw = type.getRawType();
-
- if (!Object.class.isAssignableFrom(raw)) {
- return null; // it's a primitive!
- }
-
- Constructor super T> constructor = null;
- try {
- constructor = raw.getDeclaredConstructor();
- } catch (NoSuchMethodException ignored) {
- }
-
- return new ReflectiveTypeAdapter(raw, constructor, getBoundFields(context, type, raw));
- }
-
- private Map getBoundFields(
- MiniGson context, TypeToken> type, Class> raw) {
- Map result = new LinkedHashMap();
- if (raw.isInterface()) {
- return result;
- }
-
- Type declaredType = type.getType();
- while (raw != Object.class) {
- Field[] fields = raw.getDeclaredFields();
- AccessibleObject.setAccessible(fields, true);
- for (Field field : fields) {
- boolean serialize = serializeField(raw, field, declaredType);
- boolean deserialize = deserializeField(raw, field, declaredType);
- if (serialize || deserialize) {
- Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
- BoundField boundField = createBoundField(context, field, getFieldName(raw, field, declaredType),
- TypeToken.get(fieldType), serialize, deserialize);
- BoundField previous = result.put(boundField.name, boundField);
- if (previous != null) {
- throw new IllegalArgumentException(declaredType
- + " declares multiple JSON fields named " + previous.name);
- }
- }
- }
- type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
- raw = type.getRawType();
- }
- return result;
- }
- }
-
- static abstract class BoundField {
- final String name;
- final boolean serialized;
- final boolean deserialized;
-
- protected BoundField(String name, boolean serialized, boolean deserialized) {
- this.name = name;
- this.serialized = serialized;
- this.deserialized = deserialized;
- }
-
- abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
- abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
- }
-}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java
new file mode 100644
index 00000000..05813aea
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java
@@ -0,0 +1,219 @@
+/*
+ * 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.internal.bind;
+
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.internal.$Gson$Types;
+import com.google.gson.internal.ObjectConstructor;
+import com.google.gson.internal.Primitives;
+import com.google.gson.internal.ConstructorConstructor;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Type adapter that reflects over the fields and methods of a class.
+ */
+public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ConstructorConstructor constructorConstructor;
+
+ public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
+ this.constructorConstructor = constructorConstructor;
+ }
+
+ protected boolean serializeField(Class> declaringClazz, Field f, Type declaredType) {
+ return !f.isSynthetic();
+ }
+
+ protected boolean deserializeField(Class> declaringClazz, Field f, Type declaredType) {
+ return !f.isSynthetic();
+ }
+
+ protected String getFieldName(Class> declaringClazz, Field f, Type declaredType) {
+ return f.getName();
+ }
+
+ public TypeAdapter create(MiniGson context, final TypeToken type) {
+ Class super T> raw = type.getRawType();
+
+ if (!Object.class.isAssignableFrom(raw)) {
+ return null; // it's a primitive!
+ }
+
+ ObjectConstructor constructor = constructorConstructor.getConstructor(type);
+
+ return new Adapter(context, constructor, type,
+ getBoundFields(context, type, raw));
+ }
+
+ private ReflectiveTypeAdapterFactory.BoundField createBoundField(
+ final MiniGson context, final Field field, final String name,
+ final TypeToken> fieldType, boolean serialize, boolean deserialize) {
+ final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
+
+ // special casing primitives here saves ~5% on Android...
+ return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
+ final TypeAdapter> typeAdapter = context.getAdapter(fieldType);
+ @SuppressWarnings("unchecked") // the type adapter and field type always agree
+ @Override void write(JsonWriter writer, Object value)
+ throws IOException, IllegalAccessException {
+ Object fieldValue = field.get(value);
+ TypeAdapter t =
+ new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType());
+ t.write(writer, fieldValue);
+ }
+ @Override void read(JsonReader reader, Object value)
+ throws IOException, IllegalAccessException {
+ Object fieldValue = typeAdapter.read(reader);
+ if (fieldValue != null || !isPrimitive) {
+ field.set(value, fieldValue);
+ }
+ }
+ };
+ }
+
+ private Map getBoundFields(
+ MiniGson context, TypeToken> type, Class> raw) {
+ Map result = new LinkedHashMap();
+ if (raw.isInterface()) {
+ return result;
+ }
+
+ Type declaredType = type.getType();
+ while (raw != Object.class) {
+ Field[] fields = raw.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (Field field : fields) {
+ boolean serialize = serializeField(raw, field, declaredType);
+ boolean deserialize = deserializeField(raw, field, declaredType);
+ if (!serialize && !deserialize) {
+ continue;
+ }
+ Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
+ BoundField boundField = createBoundField(context, field, getFieldName(raw, field, declaredType),
+ TypeToken.get(fieldType), serialize, deserialize);
+ BoundField previous = result.put(boundField.name, boundField);
+ if (previous != null) {
+ throw new IllegalArgumentException(declaredType
+ + " declares multiple JSON fields named " + previous.name);
+ }
+ }
+ type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
+ raw = type.getRawType();
+ }
+ return result;
+ }
+
+ static abstract class BoundField {
+ final String name;
+ final boolean serialized;
+ final boolean deserialized;
+
+ protected BoundField(String name, boolean serialized, boolean deserialized) {
+ this.name = name;
+ this.serialized = serialized;
+ this.deserialized = deserialized;
+ }
+
+ abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
+ abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
+ }
+
+ public final class Adapter extends TypeAdapter {
+ private final MiniGson context;
+ private final ObjectConstructor constructor;
+ private final TypeToken type;
+ private final Map boundFields;
+
+ private Adapter(MiniGson context, ObjectConstructor constructor,
+ TypeToken type, Map boundFields) {
+ this.context = context;
+ this.constructor = constructor;
+ this.type = type;
+ this.boundFields = boundFields;
+ }
+
+ @SuppressWarnings("unchecked") // the '? super T' is a raw T (the only kind we can construct)
+ public T read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull(); // TODO: does this belong here?
+ return null;
+ }
+
+ T instance = constructor.construct();
+
+ // TODO: null out the other fields?
+
+ try {
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ BoundField field = boundFields.get(name);
+ if (field == null || !field.deserialized) {
+ // TODO: define a better policy
+ reader.skipValue();
+ } else {
+ field.read(reader, instance);
+ }
+ }
+ } catch (IllegalStateException e) {
+ throw new JsonSyntaxException(e);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError();
+ }
+ reader.endObject();
+ return instance;
+ }
+
+ public void write(JsonWriter writer, T value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+
+ // TODO: GSON includes subclass fields during serialization
+ if (false) {
+ Class> runtimeType = value.getClass();
+ if (runtimeType != type.getRawType()) {
+ TypeAdapter> adapter = context.getAdapter(runtimeType);
+ ((TypeAdapter) adapter).write(writer, value);
+ return;
+ }
+ }
+
+ writer.beginObject();
+ try {
+ for (BoundField boundField : boundFields.values()) {
+ if (boundField.serialized) {
+ writer.name(boundField.name);
+ boundField.write(writer, value);
+ }
+ }
+ } catch (IllegalAccessException e) {
+ throw new AssertionError();
+ }
+ writer.endObject();
+ }
+ }
+}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/StringToValueMapTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/StringToValueMapTypeAdapter.java
deleted file mode 100644
index 9fbd0cbd..00000000
--- a/gson/src/main/java/com/google/gson/internal/bind/StringToValueMapTypeAdapter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.internal.bind;
-
-import com.google.gson.internal.$Gson$Types;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Adapt a map whose keys are strings.
- */
-public final class StringToValueMapTypeAdapter extends TypeAdapter> {
- public static final Factory FACTORY = new Factory() {
- public TypeAdapter create(MiniGson context, TypeToken typeToken) {
- Type type = typeToken.getType();
- if (!(type instanceof ParameterizedType)) {
- return null;
- }
-
- Class super T> rawType = typeToken.getRawType();
- if (!Map.class.isAssignableFrom(rawType)) {
- return null;
- }
-
- Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawType);
- if (keyAndValueTypes[0] != String.class) {
- return null;
- }
- TypeAdapter> valueAdapter = context.getAdapter(TypeToken.get(keyAndValueTypes[1]));
-
- Constructor> constructor;
- try {
- Class> constructorType = (rawType == Map.class) ? LinkedHashMap.class : rawType;
- constructor = constructorType.getConstructor();
- } catch (NoSuchMethodException e) {
- return null;
- }
-
- @SuppressWarnings("unchecked") // we don't define a type parameter for the key or value types
- TypeAdapter