Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Adapter Layering Feature (Java 6 Compatible) #1473

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public final class Gson {
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();

private final ConstructorConstructor constructorConstructor;
private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;
final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;

final List<TypeAdapterFactory> factories;

Expand Down Expand Up @@ -895,7 +895,9 @@ public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
if (!ReflectiveTypeAdapterFactory.Adapter.class.isAssignableFrom(getAdapter(TypeToken.get(typeOfT)).getClass())) {
assertFullConsumption(object, jsonReader);
}
return object;
}

Expand Down
61 changes: 46 additions & 15 deletions gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@

package com.google.gson;

import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
import static com.google.gson.Gson.DEFAULT_LENIENT;
import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;

import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.internal.Excluder;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import com.google.gson.internal.bind.TreeTypeAdapter;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid frivolous changes like adding final to method parameters, imports reordering, or formatting changes.

import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
Expand All @@ -26,21 +42,6 @@
import java.util.List;
import java.util.Map;

import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.Excluder;
import com.google.gson.internal.bind.TreeTypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;

import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
import static com.google.gson.Gson.DEFAULT_LENIENT;
import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;

/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
Expand Down Expand Up @@ -511,6 +512,36 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
return this;
}

/**
* Configures Gson for custom serialization and deserialization with Fill-in. Takes the type
* adapter, and wraps the result from the {@link TypeAdapter} into a {@link ReflectiveTypeAdapterFactory.Adapter}. Like
* {@link #registerTypeAdapter(Type, Object)}, it only applies to the type specified by
* the {@code type} parameter.
*
* @param baseType the type definition for the type adapter being registered
* @param objectAdapter This object must implement the {@link TypeAdapter} class
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder registerTypeAdapterWithFillIn(final Type baseType, Object objectAdapter) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this method, why not create a TypeAdapter implementation that users can extend to get fill-in features.
e.g.,
ReflectiveTypeAdapter that internally will use ReflectiveTypeAdapterFactory

$Gson$Preconditions.checkArgument(objectAdapter instanceof TypeAdapter<?>);
final TypeAdapter<?> typeAdapter = (TypeAdapter<?>) objectAdapter;

factories.add(new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
ConstructorConstructor constructorConstructor = new ConstructorConstructor(type, typeAdapter);
List<Type> typeList = new ArrayList<Type>();
typeList.add(baseType);
ReflectiveTypeAdapterFactory reflectiveTypeAdapterFactory =
new ReflectiveTypeAdapterFactory(constructorConstructor, gson.fieldNamingStrategy,
gson.excluder, gson.jsonAdapterFactory, typeList);
return reflectiveTypeAdapterFactory.create(gson, type);
}
});

return this;
}

/**
* Register a factory for type adapters. Registering a factory is useful when the type
* adapter needs to be configured based on the type of the field being processed. Gson
Expand Down
32 changes: 32 additions & 0 deletions gson/src/main/java/com/google/gson/InstanceCreatorWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.google.gson;

import com.google.gson.stream.JsonReader;
import java.lang.reflect.Type;

/**
* Acts as a wrapper of the {@link InstanceCreator} interface for fill-in. Fulfills roughly the same
* functionality as the {@link com.google.gson.internal.ObjectConstructorWrapper} class. It doesn't
* break existing functionality by implementing {@code InstanceCreator} but when casted to this
* class, it can expose a method that accepts a {@code JsonReader} as a parameter, allowing fill-in
* functionality.
*/
public class InstanceCreatorWrapper<T> implements InstanceCreator<T> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this class part of the public API?


@Override
public T createInstance(Type type) {
return null;
}

/**
* If not defined, defaults to returning the result of {@link #createInstance}. This method is
* designed to help with creating Adapters with Fill-In. See {@link
* GsonBuilder#registerTypeAdapterFactory}.
*
* @param type the parameterized T represented as a {@link Type}.
* @param in the JsonReader from which to create the instance.
* @return a default object instance of type T.
*/
public T createInstance(Type type, JsonReader in) {
return createInstance(type);
}
}
Loading