Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,14 +427,14 @@ public class Id<T> {

class IdInstanceCreator implements InstanceCreator<Id<?>> {
public Id<?> createInstance(Type type) {
Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
Type idType = typeParameters[0]; // Id has only one parameterized type T
return new Id((Class)idType, 0L);
Type[] typeArguments = TypeToken.get(type).getTypeArguments(Id.class);
Type idType = typeArguments[0]; // Id has only one parameterized type T
return new Id(TypeToken.get(idType).getRawType(), 0L);
}
}
```

In the above example, an instance of the Id class can not be created without actually passing in the actual type for the parameterized type. We solve this problem by using the passed method parameter, `type`. The `type` object in this case is the Java parameterized type representation of `Id<Foo>` where the actual instance should be bound to `Id<Foo>`. Since `Id` class has just one parameterized type parameter, `T`, we use the zeroth element of the type array returned by `getActualTypeArgument()` which will hold `Foo.class` in this case.
In the above example, an instance of the Id class can not be created without actually passing in the actual type for the parameterized type. We solve this problem by using the passed method parameter, `type`. The `type` object in this case is the Java parameterized type representation of `Id<Foo>` where the actual instance should be bound to `Id<Foo>`. We could use the methods of Java's `ParameterizedType` to get the type argument, but we use Gson's `TypeToken.getTypeArguments` instead which offers a safer and more powerful API. Since `Id` class has just one parameterized type parameter, `T`, we use the zeroth element of the `typeArguments` array which will hold `Foo.class` in this case.

### <a name="TOC-Compact-Vs.-Pretty-Printing-for-JSON-Output-Format"></a>Compact Vs. Pretty Printing for JSON Output Format

Expand Down
6 changes: 6 additions & 0 deletions gson/src/main/java/com/google/gson/TypeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@
* Gson gson = builder.create();
* }</pre>
*
* <p>When a type adapter needs to delegate to another type adapter (for example
* to serialize the elements of a generic collection) a {@link TypeAdapterFactory}
* should be used.
*
* @see GsonBuilder#registerTypeAdapter(java.lang.reflect.Type, Object)
* @see TypeAdapterFactory
* @since 2.1
*/
// non-Javadoc:
Expand Down
63 changes: 35 additions & 28 deletions gson/src/main/java/com/google/gson/TypeAdapterFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,39 @@
* Creates type adapters for set of related types. Type adapter factories are
* most useful when several types share similar structure in their JSON form.
*
* <p>Type adapter factories select which types they provide type adapters
* for. If a factory cannot support a given type, it must return null when
* that type is passed to {@link #create}. Factories should expect {@code
* create()} to be called on them for many types and should return null for
* most of those types.
*
* <p>A factory is typically called once per type, but the returned type
* adapter may be used many times. It is most efficient to do expensive work
* like reflection in {@code create()} so that the type adapter's {@code
* read()} and {@code write()} methods can be very fast.
*
* <p>Factories for generic types can use {@link TypeToken#getTypeArguments(Class)}
* to get the type arguments used for the generic supertype.
*
* <p>As with type adapters, factories must be <i>registered</i> with a {@link
* com.google.gson.GsonBuilder} for them to take effect:
* <pre>{@code
* GsonBuilder builder = new GsonBuilder();
* builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
* ...
* Gson gson = builder.create();
* }</pre>
*
* <h3>Example: Converting enums to lowercase</h3>
* In this example, we implement a factory that creates type adapters for all
* enums. The type adapters will write enums in lowercase, despite the fact
* enums. The factory returns null for calls to {@code create()} where
* {@code type} is not an enum.
*
* <p>The type adapters will write enums in lowercase, despite the fact
* that they're defined in {@code CONSTANT_CASE} in the corresponding Java
* model: <pre> {@code
* model. The mapping from lowercase name to enum value is computed eagerly
* within the factory and then used by the adapter for better performance.
* <pre>{@code
*
* public class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory {
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Expand Down Expand Up @@ -66,30 +94,6 @@
* }
* }</pre>
*
* <p>Type adapter factories select which types they provide type adapters
* for. If a factory cannot support a given type, it must return null when
* that type is passed to {@link #create}. Factories should expect {@code
* create()} to be called on them for many types and should return null for
* most of those types. In the above example the factory returns null for
* calls to {@code create()} where {@code type} is not an enum.
*
* <p>A factory is typically called once per type, but the returned type
* adapter may be used many times. It is most efficient to do expensive work
* like reflection in {@code create()} so that the type adapter's {@code
* read()} and {@code write()} methods can be very fast. In this example the
* mapping from lowercase name to enum value is computed eagerly.
*
* <p>As with type adapters, factories must be <i>registered</i> with a {@link
* com.google.gson.GsonBuilder} for them to take effect: <pre> {@code
*
* GsonBuilder builder = new GsonBuilder();
* builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
* ...
* Gson gson = builder.create();
* }</pre>
* If multiple factories support the same type, the factory registered earlier
* takes precedence.
*
* <h3>Example: composing other type adapters</h3>
* In this example we implement a factory for Guava's {@code Multiset}
* collection type. The factory can be used to create type adapters for
Expand All @@ -100,7 +104,8 @@
* <p>The type adapter <i>delegates</i> to another type adapter for the
* multiset elements. It figures out the element type by reflecting on the
* multiset's type token. A {@code Gson} is passed in to {@code create} for
* just this purpose: <pre> {@code
* just this purpose:
* <pre>{@code
*
* public class MultisetTypeAdapterFactory implements TypeAdapterFactory {
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Expand All @@ -110,7 +115,7 @@
* return null;
* }
*
* Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
* Type elementType = typeToken.getTypeArguments(Multiset.class)[0];
* TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));
* return (TypeAdapter<T>) newMultisetAdapter(elementAdapter);
* }
Expand Down Expand Up @@ -159,6 +164,8 @@
* creation happens only once.
*
* @since 2.1
* @see GsonBuilder#registerTypeAdapterFactory(TypeAdapterFactory)
* @see TypeAdapter
*/
public interface TypeAdapterFactory {

Expand Down
Loading