| /* | 
|  * 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 cn.emay.sdk.util.json.gson; | 
|   | 
| import java.io.EOFException; | 
| import java.io.IOException; | 
| import java.io.Reader; | 
| import java.io.StringReader; | 
| import java.io.StringWriter; | 
| import java.io.Writer; | 
| import java.lang.reflect.Type; | 
| import java.math.BigDecimal; | 
| import java.math.BigInteger; | 
| import java.util.ArrayList; | 
| import java.util.Collections; | 
| import java.util.HashMap; | 
| import java.util.List; | 
| import java.util.Map; | 
| import java.util.concurrent.atomic.AtomicLong; | 
| import java.util.concurrent.atomic.AtomicLongArray; | 
|   | 
| import cn.emay.sdk.util.json.gson.internal.ConstructorConstructor; | 
| import cn.emay.sdk.util.json.gson.internal.Excluder; | 
| import cn.emay.sdk.util.json.gson.internal.Primitives; | 
| import cn.emay.sdk.util.json.gson.internal.Streams; | 
| import cn.emay.sdk.util.json.gson.internal.bind.ArrayTypeAdapter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.CollectionTypeAdapterFactory; | 
| import cn.emay.sdk.util.json.gson.internal.bind.DateTypeAdapter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory; | 
| import cn.emay.sdk.util.json.gson.internal.bind.JsonTreeReader; | 
| import cn.emay.sdk.util.json.gson.internal.bind.JsonTreeWriter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.MapTypeAdapterFactory; | 
| import cn.emay.sdk.util.json.gson.internal.bind.ObjectTypeAdapter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.ReflectiveTypeAdapterFactory; | 
| import cn.emay.sdk.util.json.gson.internal.bind.SqlDateTypeAdapter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.TimeTypeAdapter; | 
| import cn.emay.sdk.util.json.gson.internal.bind.TypeAdapters; | 
| import cn.emay.sdk.util.json.gson.reflect.TypeToken; | 
| import cn.emay.sdk.util.json.gson.stream.JsonReader; | 
| import cn.emay.sdk.util.json.gson.stream.JsonToken; | 
| import cn.emay.sdk.util.json.gson.stream.JsonWriter; | 
| import cn.emay.sdk.util.json.gson.stream.MalformedJsonException; | 
|   | 
| /** | 
|  * This is the main class for using Gson. Gson is typically used by first | 
|  * constructing a Gson instance and then invoking {@link #toJson(Object)} or | 
|  * {@link #fromJson(String, Class)} methods on it. Gson instances are | 
|  * Thread-safe so you can reuse them freely across multiple threads. | 
|  * | 
|  * <p> | 
|  * You can create a Gson instance by invoking {@code new Gson()} if the default | 
|  * configuration is all you need. You can also use {@link GsonBuilder} to build | 
|  * a Gson instance with various configuration options such as versioning | 
|  * support, pretty printing, custom {@link JsonSerializer}s, | 
|  * {@link JsonDeserializer}s, and {@link InstanceCreator}s. | 
|  * </p> | 
|  * | 
|  * <p> | 
|  * Here is an example of how Gson is used for a simple Class: | 
|  * | 
|  * <pre> | 
|  * Gson gson = new Gson(); // Or use new GsonBuilder().create(); | 
|  * MyType target = new MyType(); | 
|  * String json = gson.toJson(target); // serializes target to Json | 
|  * MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2 | 
|  * </pre> | 
|  * </p> | 
|  * | 
|  * <p> | 
|  * If the object that your are serializing/deserializing is a | 
|  * {@code ParameterizedType} (i.e. contains at least one type parameter and may | 
|  * be an array) then you must use the {@link #toJson(Object, Type)} or | 
|  * {@link #fromJson(String, Type)} method. Here is an example for serializing | 
|  * and deserializing a {@code ParameterizedType}: | 
|  * | 
|  * <pre> | 
|  * Type listType = new TypeToken<List<String>>() { | 
|  * }.getType(); | 
|  * List<String> target = new LinkedList<String>(); | 
|  * target.add("blah"); | 
|  * | 
|  * Gson gson = new Gson(); | 
|  * String json = gson.toJson(target, listType); | 
|  * List<String> target2 = gson.fromJson(json, listType); | 
|  * </pre> | 
|  * </p> | 
|  * | 
|  * <p> | 
|  * See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson | 
|  * User Guide</a> for a more complete set of examples. | 
|  * </p> | 
|  * | 
|  * @see com.google.gson.reflect.TypeToken | 
|  * | 
|  * @author Inderjeet Singh | 
|  * @author Joel Leitch | 
|  * @author Jesse Wilson | 
|  */ | 
| public final class Gson { | 
|     static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; | 
|     static final boolean DEFAULT_LENIENT = false; | 
|     static final boolean DEFAULT_PRETTY_PRINT = false; | 
|     static final boolean DEFAULT_ESCAPE_HTML = true; | 
|     static final boolean DEFAULT_SERIALIZE_NULLS = false; | 
|     static final boolean DEFAULT_COMPLEX_MAP_KEYS = false; | 
|     static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false; | 
|   | 
|     private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; | 
|   | 
|     /** | 
|      * This thread local guards against reentrant calls to getAdapter(). In certain | 
|      * object graphs, creating an adapter for a type may recursively require an | 
|      * adapter for the same type! Without intervention, the recursive lookup would | 
|      * stack overflow. We cheat by returning a proxy type adapter. The proxy is | 
|      * wired up once the initial adapter has been created. | 
|      */ | 
|     private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls = new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>(); | 
|   | 
|     private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = Collections.synchronizedMap(new HashMap<TypeToken<?>, TypeAdapter<?>>()); | 
|   | 
|     private final List<TypeAdapterFactory> factories; | 
|     private final ConstructorConstructor constructorConstructor; | 
|   | 
|     private final boolean serializeNulls; | 
|     private final boolean htmlSafe; | 
|     private final boolean generateNonExecutableJson; | 
|     private final boolean prettyPrinting; | 
|     private final boolean lenient; | 
|   | 
|     final JsonDeserializationContext deserializationContext = new JsonDeserializationContext() { | 
|         @SuppressWarnings("unchecked") | 
|         @Override | 
|         public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException { | 
|             return (T) fromJson(json, typeOfT); | 
|         } | 
|     }; | 
|   | 
|     final JsonSerializationContext serializationContext = new JsonSerializationContext() { | 
|         @Override | 
|         public JsonElement serialize(Object src) { | 
|             return toJsonTree(src); | 
|         } | 
|   | 
|         @Override | 
|         public JsonElement serialize(Object src, Type typeOfSrc) { | 
|             return toJsonTree(src, typeOfSrc); | 
|         } | 
|     }; | 
|   | 
|     /** | 
|      * Constructs a Gson object with default configuration. The default | 
|      * configuration has the following settings: | 
|      * <ul> | 
|      * <li>The JSON generated by <code>toJson</code> methods is in compact | 
|      * representation. This means that all the unneeded white-space is removed. You | 
|      * can change this behavior with {@link GsonBuilder#setPrettyPrinting()}.</li> | 
|      * <li>The generated JSON omits all the fields that are null. Note that nulls in | 
|      * arrays are kept as is since an array is an ordered list. Moreover, if a field | 
|      * is not null, but its generated JSON is empty, the field is kept. You can | 
|      * configure Gson to serialize null values by setting | 
|      * {@link GsonBuilder#serializeNulls()}.</li> | 
|      * <li>Gson provides default serialization and deserialization for Enums, | 
|      * {@link Map}, {@link java.net.URL}, {@link java.net.URI}, | 
|      * {@link java.util.Locale}, {@link java.util.Date}, | 
|      * {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If | 
|      * you would prefer to change the default representation, you can do so by | 
|      * registering a type adapter through | 
|      * {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</li> | 
|      * <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. | 
|      * This format ignores the millisecond portion of the date during serialization. | 
|      * You can change this by invoking {@link GsonBuilder#setDateFormat(int)} or | 
|      * {@link GsonBuilder#setDateFormat(String)}.</li> | 
|      * <li>By default, Gson ignores the {@link com.google.gson.annotations.Expose} | 
|      * annotation. You can enable Gson to serialize/deserialize only those fields | 
|      * marked with this annotation through | 
|      * {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}.</li> | 
|      * <li>By default, Gson ignores the {@link com.google.gson.annotations.Since} | 
|      * annotation. You can enable Gson to use this annotation through | 
|      * {@link GsonBuilder#setVersion(double)}.</li> | 
|      * <li>The default field naming policy for the output Json is same as in Java. | 
|      * So, a Java class field <code>versionNumber</code> will be output as | 
|      * <code>"versionNumber"</code> in Json. The same rules are applied | 
|      * for mapping incoming Json to the Java classes. You can change this policy | 
|      * through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.</li> | 
|      * <li>By default, Gson excludes <code>transient</code> or <code>static</code> | 
|      * fields from consideration for serialization and deserialization. You can | 
|      * change this behavior through | 
|      * {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li> | 
|      * </ul> | 
|      */ | 
|     public Gson() { | 
|         this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS, DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, | 
|                 DEFAULT_ESCAPE_HTML, DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES, LongSerializationPolicy.DEFAULT, Collections.<TypeAdapterFactory>emptyList()); | 
|     } | 
|   | 
|     Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy, final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, | 
|             boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, | 
|             List<TypeAdapterFactory> typeAdapterFactories) { | 
|         this.constructorConstructor = new ConstructorConstructor(instanceCreators); | 
|         this.serializeNulls = serializeNulls; | 
|         this.generateNonExecutableJson = generateNonExecutableGson; | 
|         this.htmlSafe = htmlSafe; | 
|         this.prettyPrinting = prettyPrinting; | 
|         this.lenient = lenient; | 
|   | 
|         List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(); | 
|   | 
|         // built-in type adapters that cannot be overridden | 
|         factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); | 
|         factories.add(ObjectTypeAdapter.FACTORY); | 
|   | 
|         // the excluder must precede all adapters that handle user-defined types | 
|         factories.add(excluder); | 
|   | 
|         // user's type adapters | 
|         factories.addAll(typeAdapterFactories); | 
|   | 
|         // type adapters for basic platform types | 
|         factories.add(TypeAdapters.STRING_FACTORY); | 
|         factories.add(TypeAdapters.INTEGER_FACTORY); | 
|         factories.add(TypeAdapters.BOOLEAN_FACTORY); | 
|         factories.add(TypeAdapters.BYTE_FACTORY); | 
|         factories.add(TypeAdapters.SHORT_FACTORY); | 
|         TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy); | 
|         factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); | 
|         factories.add(TypeAdapters.newFactory(double.class, Double.class, doubleAdapter(serializeSpecialFloatingPointValues))); | 
|         factories.add(TypeAdapters.newFactory(float.class, Float.class, floatAdapter(serializeSpecialFloatingPointValues))); | 
|         factories.add(TypeAdapters.NUMBER_FACTORY); | 
|         factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); | 
|         factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); | 
|         factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter))); | 
|         factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter))); | 
|         factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY); | 
|         factories.add(TypeAdapters.CHARACTER_FACTORY); | 
|         factories.add(TypeAdapters.STRING_BUILDER_FACTORY); | 
|         factories.add(TypeAdapters.STRING_BUFFER_FACTORY); | 
|         factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); | 
|         factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); | 
|         factories.add(TypeAdapters.URL_FACTORY); | 
|         factories.add(TypeAdapters.URI_FACTORY); | 
|         factories.add(TypeAdapters.UUID_FACTORY); | 
|         factories.add(TypeAdapters.CURRENCY_FACTORY); | 
|         factories.add(TypeAdapters.LOCALE_FACTORY); | 
|         factories.add(TypeAdapters.INET_ADDRESS_FACTORY); | 
|         factories.add(TypeAdapters.BIT_SET_FACTORY); | 
|         factories.add(DateTypeAdapter.FACTORY); | 
|         factories.add(TypeAdapters.CALENDAR_FACTORY); | 
|         factories.add(TimeTypeAdapter.FACTORY); | 
|         factories.add(SqlDateTypeAdapter.FACTORY); | 
|         factories.add(TypeAdapters.TIMESTAMP_FACTORY); | 
|         factories.add(ArrayTypeAdapter.FACTORY); | 
|         factories.add(TypeAdapters.CLASS_FACTORY); | 
|   | 
|         // type adapters for composite and user-defined types | 
|         factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); | 
|         factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); | 
|         factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor)); | 
|         factories.add(TypeAdapters.ENUM_FACTORY); | 
|         factories.add(new ReflectiveTypeAdapterFactory(constructorConstructor, fieldNamingPolicy, excluder)); | 
|   | 
|         this.factories = Collections.unmodifiableList(factories); | 
|     } | 
|   | 
|     private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) { | 
|         if (serializeSpecialFloatingPointValues) { | 
|             return TypeAdapters.DOUBLE; | 
|         } | 
|         return new TypeAdapter<Number>() { | 
|             @Override | 
|             public Double read(JsonReader in) throws IOException { | 
|                 if (in.peek() == JsonToken.NULL) { | 
|                     in.nextNull(); | 
|                     return null; | 
|                 } | 
|                 return in.nextDouble(); | 
|             } | 
|   | 
|             @Override | 
|             public void write(JsonWriter out, Number value) throws IOException { | 
|                 if (value == null) { | 
|                     out.nullValue(); | 
|                     return; | 
|                 } | 
|                 double doubleValue = value.doubleValue(); | 
|                 checkValidFloatingPoint(doubleValue); | 
|                 out.value(value); | 
|             } | 
|         }; | 
|     } | 
|   | 
|     private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) { | 
|         if (serializeSpecialFloatingPointValues) { | 
|             return TypeAdapters.FLOAT; | 
|         } | 
|         return new TypeAdapter<Number>() { | 
|             @Override | 
|             public Float read(JsonReader in) throws IOException { | 
|                 if (in.peek() == JsonToken.NULL) { | 
|                     in.nextNull(); | 
|                     return null; | 
|                 } | 
|                 return (float) in.nextDouble(); | 
|             } | 
|   | 
|             @Override | 
|             public void write(JsonWriter out, Number value) throws IOException { | 
|                 if (value == null) { | 
|                     out.nullValue(); | 
|                     return; | 
|                 } | 
|                 float floatValue = value.floatValue(); | 
|                 checkValidFloatingPoint(floatValue); | 
|                 out.value(value); | 
|             } | 
|         }; | 
|     } | 
|   | 
|     static void checkValidFloatingPoint(double value) { | 
|         if (Double.isNaN(value) || Double.isInfinite(value)) { | 
|             throw new IllegalArgumentException( | 
|                     value + " is not a valid double value as per JSON specification. To override this" + " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method."); | 
|         } | 
|     } | 
|   | 
|     private static TypeAdapter<Number> longAdapter(LongSerializationPolicy longSerializationPolicy) { | 
|         if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) { | 
|             return TypeAdapters.LONG; | 
|         } | 
|         return new TypeAdapter<Number>() { | 
|             @Override | 
|             public Number read(JsonReader in) throws IOException { | 
|                 if (in.peek() == JsonToken.NULL) { | 
|                     in.nextNull(); | 
|                     return null; | 
|                 } | 
|                 return in.nextLong(); | 
|             } | 
|   | 
|             @Override | 
|             public void write(JsonWriter out, Number value) throws IOException { | 
|                 if (value == null) { | 
|                     out.nullValue(); | 
|                     return; | 
|                 } | 
|                 out.value(value.toString()); | 
|             } | 
|         }; | 
|     } | 
|   | 
|     private static TypeAdapter<AtomicLong> atomicLongAdapter(final TypeAdapter<Number> longAdapter) { | 
|         return new TypeAdapter<AtomicLong>() { | 
|             @Override | 
|             public void write(JsonWriter out, AtomicLong value) throws IOException { | 
|                 longAdapter.write(out, value.get()); | 
|             } | 
|   | 
|             @Override | 
|             public AtomicLong read(JsonReader in) throws IOException { | 
|                 Number value = longAdapter.read(in); | 
|                 return new AtomicLong(value.longValue()); | 
|             } | 
|         }.nullSafe(); | 
|     } | 
|   | 
|     private static TypeAdapter<AtomicLongArray> atomicLongArrayAdapter(final TypeAdapter<Number> longAdapter) { | 
|         return new TypeAdapter<AtomicLongArray>() { | 
|             @Override | 
|             public void write(JsonWriter out, AtomicLongArray value) throws IOException { | 
|                 out.beginArray(); | 
|                 for (int i = 0, length = value.length(); i < length; i++) { | 
|                     longAdapter.write(out, value.get(i)); | 
|                 } | 
|                 out.endArray(); | 
|             } | 
|   | 
|             @Override | 
|             public AtomicLongArray read(JsonReader in) throws IOException { | 
|                 List<Long> list = new ArrayList<Long>(); | 
|                 in.beginArray(); | 
|                 while (in.hasNext()) { | 
|                     long value = longAdapter.read(in).longValue(); | 
|                     list.add(value); | 
|                 } | 
|                 in.endArray(); | 
|                 int length = list.size(); | 
|                 AtomicLongArray array = new AtomicLongArray(length); | 
|                 for (int i = 0; i < length; ++i) { | 
|                     array.set(i, list.get(i)); | 
|                 } | 
|                 return array; | 
|             } | 
|         }.nullSafe(); | 
|     } | 
|   | 
|     /** | 
|      * Returns the type adapter for {@code} type. | 
|      * | 
|      * @throws IllegalArgumentException | 
|      *             if this GSON cannot serialize and deserialize {@code type}. | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) { | 
|         TypeAdapter<?> cached = typeTokenCache.get(type); | 
|         if (cached != null) { | 
|             return (TypeAdapter<T>) cached; | 
|         } | 
|   | 
|         Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get(); | 
|         boolean requiresThreadLocalCleanup = false; | 
|         if (threadCalls == null) { | 
|             threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>(); | 
|             calls.set(threadCalls); | 
|             requiresThreadLocalCleanup = true; | 
|         } | 
|   | 
|         // the key and value type parameters always agree | 
|         FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type); | 
|         if (ongoingCall != null) { | 
|             return ongoingCall; | 
|         } | 
|   | 
|         try { | 
|             FutureTypeAdapter<T> call = new FutureTypeAdapter<T>(); | 
|             threadCalls.put(type, call); | 
|   | 
|             for (TypeAdapterFactory factory : factories) { | 
|                 TypeAdapter<T> candidate = factory.create(this, type); | 
|                 if (candidate != null) { | 
|                     call.setDelegate(candidate); | 
|                     typeTokenCache.put(type, candidate); | 
|                     return candidate; | 
|                 } | 
|             } | 
|             throw new IllegalArgumentException("GSON cannot handle " + type); | 
|         } finally { | 
|             threadCalls.remove(type); | 
|   | 
|             if (requiresThreadLocalCleanup) { | 
|                 calls.remove(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * This method is used to get an alternate type adapter for the specified type. | 
|      * This is used to access a type adapter that is overridden by a | 
|      * {@link TypeAdapterFactory} that you may have registered. This features is | 
|      * typically used when you want to register a type adapter that does a little | 
|      * bit of work but then delegates further processing to the Gson default type | 
|      * adapter. Here is an example: | 
|      * <p> | 
|      * Let's say we want to write a type adapter that counts the number of objects | 
|      * being read from or written to JSON. We can achieve this by writing a type | 
|      * adapter factory that uses the <code>getDelegateAdapter</code> method: | 
|      *  | 
|      * <pre> | 
|      * { | 
|      *     @code | 
|      *     class StatsTypeAdapterFactory implements TypeAdapterFactory { | 
|      *         public int numReads = 0; | 
|      *         public int numWrites = 0; | 
|      *  | 
|      *         public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { | 
|      *             final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); | 
|      *             return new TypeAdapter<T>() { | 
|      *                 public void write(JsonWriter out, T value) throws IOException { | 
|      *                     ++numWrites; | 
|      *                     delegate.write(out, value); | 
|      *                 } | 
|      *  | 
|      *                 public T read(JsonReader in) throws IOException { | 
|      *                     ++numReads; | 
|      *                     return delegate.read(in); | 
|      *                 } | 
|      *             }; | 
|      *         } | 
|      *     } | 
|      * } | 
|      * </pre> | 
|      *  | 
|      * This factory can now be used like this: | 
|      *  | 
|      * <pre> | 
|      * { | 
|      *     @code | 
|      *     StatsTypeAdapterFactory stats = new StatsTypeAdapterFactory(); | 
|      *     Gson gson = new GsonBuilder().registerTypeAdapterFactory(stats).create(); | 
|      *     // Call gson.toJson() and fromJson methods on objects | 
|      *     System.out.println("Num JSON reads" + stats.numReads); | 
|      *     System.out.println("Num JSON writes" + stats.numWrites); | 
|      * } | 
|      * </pre> | 
|      *  | 
|      * Note that this call will skip all factories registered before | 
|      * {@code skipPast}. In case of multiple TypeAdapterFactories registered it is | 
|      * up to the caller of this function to insure that the order of registration | 
|      * does not prevent this method from reaching a factory they would expect to | 
|      * reply from this call. Note that since you can not override type adapter | 
|      * factories for String and Java primitive types, our stats factory will not | 
|      * count the number of String or primitives that will be read or written. | 
|      *  | 
|      * @param skipPast | 
|      *            The type adapter factory that needs to be skipped while searching | 
|      *            for a matching type adapter. In most cases, you should just pass | 
|      *            <i>this</i> (the type adapter factory from where | 
|      *            {@link #getDelegateAdapter} method is being invoked). | 
|      * @param type | 
|      *            Type for which the delegate adapter is being searched for. | 
|      * | 
|      * @since 2.2 | 
|      */ | 
|     public <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type) { | 
|         boolean skipPastFound = false; | 
|         // Skip past if and only if the specified factory is present in the factories. | 
|         // This is useful because the factories created through JsonAdapter annotations | 
|         // are not | 
|         // registered in this list. | 
|         if (!factories.contains(skipPast)) | 
|             skipPastFound = true; | 
|   | 
|         for (TypeAdapterFactory factory : factories) { | 
|             if (!skipPastFound) { | 
|                 if (factory == skipPast) { | 
|                     skipPastFound = true; | 
|                 } | 
|                 continue; | 
|             } | 
|   | 
|             TypeAdapter<T> candidate = factory.create(this, type); | 
|             if (candidate != null) { | 
|                 return candidate; | 
|             } | 
|         } | 
|         throw new IllegalArgumentException("GSON cannot serialize " + type); | 
|     } | 
|   | 
|     /** | 
|      * Returns the type adapter for {@code} type. | 
|      * | 
|      * @throws IllegalArgumentException | 
|      *             if this GSON cannot serialize and deserialize {@code type}. | 
|      */ | 
|     public <T> TypeAdapter<T> getAdapter(Class<T> type) { | 
|         return getAdapter(TypeToken.get(type)); | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object into its equivalent | 
|      * representation as a tree of {@link JsonElement}s. This method should be used | 
|      * when the specified object is not a generic type. This method uses | 
|      * {@link Class#getClass()} to get the type for the specified object, but the | 
|      * {@code getClass()} loses the generic type information because of the Type | 
|      * Erasure feature of Java. Note that this method works fine if the any of the | 
|      * object fields are of generic type, just the object itself should not be of a | 
|      * generic type. If the object is of generic type, use | 
|      * {@link #toJsonTree(Object, Type)} instead. | 
|      * | 
|      * @param src | 
|      *            the object for which Json representation is to be created setting | 
|      *            for Gson | 
|      * @return Json representation of {@code src}. | 
|      * @since 1.4 | 
|      */ | 
|     public JsonElement toJsonTree(Object src) { | 
|         if (src == null) { | 
|             return JsonNull.INSTANCE; | 
|         } | 
|         return toJsonTree(src, src.getClass()); | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object, including those of generic | 
|      * types, into its equivalent representation as a tree of {@link JsonElement}s. | 
|      * This method must be used if the specified object is a generic type. For | 
|      * non-generic objects, use {@link #toJsonTree(Object)} instead. | 
|      * | 
|      * @param src | 
|      *            the object for which JSON representation is to be created | 
|      * @param typeOfSrc | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfSrc = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @return Json representation of {@code src} | 
|      * @since 1.4 | 
|      */ | 
|     public JsonElement toJsonTree(Object src, Type typeOfSrc) { | 
|         JsonTreeWriter writer = new JsonTreeWriter(); | 
|         toJson(src, typeOfSrc, writer); | 
|         return writer.get(); | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object into its equivalent Json | 
|      * representation. This method should be used when the specified object is not a | 
|      * generic type. This method uses {@link Class#getClass()} to get the type for | 
|      * the specified object, but the {@code getClass()} loses the generic type | 
|      * information because of the Type Erasure feature of Java. Note that this | 
|      * method works fine if the any of the object fields are of generic type, just | 
|      * the object itself should not be of a generic type. If the object is of | 
|      * generic type, use {@link #toJson(Object, Type)} instead. If you want to write | 
|      * out the object to a {@link Writer}, use {@link #toJson(Object, Appendable)} | 
|      * instead. | 
|      * | 
|      * @param src | 
|      *            the object for which Json representation is to be created setting | 
|      *            for Gson | 
|      * @return Json representation of {@code src}. | 
|      */ | 
|     public String toJson(Object src) { | 
|         if (src == null) { | 
|             return toJson(JsonNull.INSTANCE); | 
|         } | 
|         return toJson(src, src.getClass()); | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object, including those of generic | 
|      * types, into its equivalent Json representation. This method must be used if | 
|      * the specified object is a generic type. For non-generic objects, use | 
|      * {@link #toJson(Object)} instead. If you want to write out the object to a | 
|      * {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead. | 
|      * | 
|      * @param src | 
|      *            the object for which JSON representation is to be created | 
|      * @param typeOfSrc | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfSrc = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @return Json representation of {@code src} | 
|      */ | 
|     public String toJson(Object src, Type typeOfSrc) { | 
|         StringWriter writer = new StringWriter(); | 
|         toJson(src, typeOfSrc, writer); | 
|         return writer.toString(); | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object into its equivalent Json | 
|      * representation. This method should be used when the specified object is not a | 
|      * generic type. This method uses {@link Class#getClass()} to get the type for | 
|      * the specified object, but the {@code getClass()} loses the generic type | 
|      * information because of the Type Erasure feature of Java. Note that this | 
|      * method works fine if the any of the object fields are of generic type, just | 
|      * the object itself should not be of a generic type. If the object is of | 
|      * generic type, use {@link #toJson(Object, Type, Appendable)} instead. | 
|      * | 
|      * @param src | 
|      *            the object for which Json representation is to be created setting | 
|      *            for Gson | 
|      * @param writer | 
|      *            Writer to which the Json representation needs to be written | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the writer | 
|      * @since 1.2 | 
|      */ | 
|     public void toJson(Object src, Appendable writer) throws JsonIOException { | 
|         if (src != null) { | 
|             toJson(src, src.getClass(), writer); | 
|         } else { | 
|             toJson(JsonNull.INSTANCE, writer); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * This method serializes the specified object, including those of generic | 
|      * types, into its equivalent Json representation. This method must be used if | 
|      * the specified object is a generic type. For non-generic objects, use | 
|      * {@link #toJson(Object, Appendable)} instead. | 
|      * | 
|      * @param src | 
|      *            the object for which JSON representation is to be created | 
|      * @param typeOfSrc | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfSrc = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @param writer | 
|      *            Writer to which the Json representation of src needs to be | 
|      *            written. | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the writer | 
|      * @since 1.2 | 
|      */ | 
|     public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException { | 
|         try { | 
|             JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); | 
|             toJson(src, typeOfSrc, jsonWriter); | 
|         } catch (IOException e) { | 
|             throw new JsonIOException(e); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * Writes the JSON representation of {@code src} of type {@code typeOfSrc} to | 
|      * {@code writer}. | 
|      *  | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the writer | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { | 
|         TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); | 
|         boolean oldLenient = writer.isLenient(); | 
|         writer.setLenient(true); | 
|         boolean oldHtmlSafe = writer.isHtmlSafe(); | 
|         writer.setHtmlSafe(htmlSafe); | 
|         boolean oldSerializeNulls = writer.getSerializeNulls(); | 
|         writer.setSerializeNulls(serializeNulls); | 
|         try { | 
|             ((TypeAdapter<Object>) adapter).write(writer, src); | 
|         } catch (IOException e) { | 
|             throw new JsonIOException(e); | 
|         } finally { | 
|             writer.setLenient(oldLenient); | 
|             writer.setHtmlSafe(oldHtmlSafe); | 
|             writer.setSerializeNulls(oldSerializeNulls); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * Converts a tree of {@link JsonElement}s into its equivalent JSON | 
|      * representation. | 
|      * | 
|      * @param jsonElement | 
|      *            root of a tree of {@link JsonElement}s | 
|      * @return JSON String representation of the tree | 
|      * @since 1.4 | 
|      */ | 
|     public String toJson(JsonElement jsonElement) { | 
|         StringWriter writer = new StringWriter(); | 
|         toJson(jsonElement, writer); | 
|         return writer.toString(); | 
|     } | 
|   | 
|     /** | 
|      * Writes out the equivalent JSON for a tree of {@link JsonElement}s. | 
|      * | 
|      * @param jsonElement | 
|      *            root of a tree of {@link JsonElement}s | 
|      * @param writer | 
|      *            Writer to which the Json representation needs to be written | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the writer | 
|      * @since 1.4 | 
|      */ | 
|     public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException { | 
|         try { | 
|             JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); | 
|             toJson(jsonElement, jsonWriter); | 
|         } catch (IOException e) { | 
|             throw new RuntimeException(e); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * Returns a new JSON writer configured for the settings on this Gson instance. | 
|      */ | 
|     public JsonWriter newJsonWriter(Writer writer) throws IOException { | 
|         if (generateNonExecutableJson) { | 
|             writer.write(JSON_NON_EXECUTABLE_PREFIX); | 
|         } | 
|         JsonWriter jsonWriter = new JsonWriter(writer); | 
|         if (prettyPrinting) { | 
|             jsonWriter.setIndent("  "); | 
|         } | 
|         jsonWriter.setSerializeNulls(serializeNulls); | 
|         return jsonWriter; | 
|     } | 
|   | 
|     /** | 
|      * Returns a new JSON writer configured for the settings on this Gson instance. | 
|      */ | 
|     public JsonReader newJsonReader(Reader reader) { | 
|         JsonReader jsonReader = new JsonReader(reader); | 
|         jsonReader.setLenient(lenient); | 
|         return jsonReader; | 
|     } | 
|   | 
|     /** | 
|      * Writes the JSON for {@code jsonElement} to {@code writer}. | 
|      *  | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the writer | 
|      */ | 
|     public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException { | 
|         boolean oldLenient = writer.isLenient(); | 
|         writer.setLenient(true); | 
|         boolean oldHtmlSafe = writer.isHtmlSafe(); | 
|         writer.setHtmlSafe(htmlSafe); | 
|         boolean oldSerializeNulls = writer.getSerializeNulls(); | 
|         writer.setSerializeNulls(serializeNulls); | 
|         try { | 
|             Streams.write(jsonElement, writer); | 
|         } catch (IOException e) { | 
|             throw new JsonIOException(e); | 
|         } finally { | 
|             writer.setLenient(oldLenient); | 
|             writer.setHtmlSafe(oldHtmlSafe); | 
|             writer.setSerializeNulls(oldSerializeNulls); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the specified Json into an object of the specified | 
|      * class. It is not suitable to use if the specified class is a generic type | 
|      * since it will not have the generic type information because of the Type | 
|      * Erasure feature of Java. Therefore, this method should not be used if the | 
|      * desired type is a generic type. Note that this method works fine if the any | 
|      * of the fields of the specified object are generics, just the object itself | 
|      * should not be a generic type. For the cases when the object is of generic | 
|      * type, invoke {@link #fromJson(String, Type)}. If you have the Json in a | 
|      * {@link Reader} instead of a String, use {@link #fromJson(Reader, Class)} | 
|      * instead. | 
|      * | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the string from which the object is to be deserialized | 
|      * @param classOfT | 
|      *            the class of T | 
|      * @return an object of type T from the string. Returns {@code null} if | 
|      *         {@code json} is {@code null}. | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      *             classOfT | 
|      */ | 
|     public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException { | 
|         Object object = fromJson(json, (Type) classOfT); | 
|         return Primitives.wrap(classOfT).cast(object); | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the specified Json into an object of the specified | 
|      * type. This method is useful if the specified object is a generic type. For | 
|      * non-generic objects, use {@link #fromJson(String, Class)} instead. If you | 
|      * have the Json in a {@link Reader} instead of a String, use | 
|      * {@link #fromJson(Reader, Type)} instead. | 
|      * | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the string from which the object is to be deserialized | 
|      * @param typeOfT | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfT = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @return an object of type T from the string. Returns {@code null} if | 
|      *         {@code json} is {@code null}. | 
|      * @throws JsonParseException | 
|      *             if json is not a valid representation for an object of type | 
|      *             typeOfT | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException { | 
|         if (json == null) { | 
|             return null; | 
|         } | 
|         StringReader reader = new StringReader(json); | 
|         T target = (T) fromJson(reader, typeOfT); | 
|         return target; | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the Json read from the specified reader into an | 
|      * object of the specified class. It is not suitable to use if the specified | 
|      * class is a generic type since it will not have the generic type information | 
|      * because of the Type Erasure feature of Java. Therefore, this method should | 
|      * not be used if the desired type is a generic type. Note that this method | 
|      * works fine if the any of the fields of the specified object are generics, | 
|      * just the object itself should not be a generic type. For the cases when the | 
|      * object is of generic type, invoke {@link #fromJson(Reader, Type)}. If you | 
|      * have the Json in a String form instead of a {@link Reader}, use | 
|      * {@link #fromJson(String, Class)} instead. | 
|      * | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the reader producing the Json from which the object is to be | 
|      *            deserialized. | 
|      * @param classOfT | 
|      *            the class of T | 
|      * @return an object of type T from the string. Returns {@code null} if | 
|      *         {@code json} is at EOF. | 
|      * @throws JsonIOException | 
|      *             if there was a problem reading from the Reader | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      * @since 1.2 | 
|      */ | 
|     public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException { | 
|         JsonReader jsonReader = newJsonReader(json); | 
|         Object object = fromJson(jsonReader, classOfT); | 
|         assertFullConsumption(object, jsonReader); | 
|         return Primitives.wrap(classOfT).cast(object); | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the Json read from the specified reader into an | 
|      * object of the specified type. This method is useful if the specified object | 
|      * is a generic type. For non-generic objects, use | 
|      * {@link #fromJson(Reader, Class)} instead. If you have the Json in a String | 
|      * form instead of a {@link Reader}, use {@link #fromJson(String, Type)} | 
|      * instead. | 
|      * | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the reader producing Json from which the object is to be | 
|      *            deserialized | 
|      * @param typeOfT | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfT = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @return an object of type T from the json. Returns {@code null} if | 
|      *         {@code json} is at EOF. | 
|      * @throws JsonIOException | 
|      *             if there was a problem reading from the Reader | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      * @since 1.2 | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { | 
|         JsonReader jsonReader = newJsonReader(json); | 
|         T object = (T) fromJson(jsonReader, typeOfT); | 
|         assertFullConsumption(object, jsonReader); | 
|         return object; | 
|     } | 
|   | 
|     private static void assertFullConsumption(Object obj, JsonReader reader) { | 
|         try { | 
|             if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { | 
|                 throw new JsonIOException("JSON document was not fully consumed."); | 
|             } | 
|         } catch (MalformedJsonException e) { | 
|             throw new JsonSyntaxException(e); | 
|         } catch (IOException e) { | 
|             throw new JsonIOException(e); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * Reads the next JSON value from {@code reader} and convert it to an object of | 
|      * type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF. | 
|      * Since Type is not parameterized by T, this method is type unsafe and should | 
|      * be used carefully | 
|      * | 
|      * @throws JsonIOException | 
|      *             if there was a problem writing to the Reader | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { | 
|         boolean isEmpty = true; | 
|         boolean oldLenient = reader.isLenient(); | 
|         reader.setLenient(true); | 
|         try { | 
|             reader.peek(); | 
|             isEmpty = false; | 
|             TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT); | 
|             TypeAdapter<T> typeAdapter = getAdapter(typeToken); | 
|             T object = typeAdapter.read(reader); | 
|             return object; | 
|         } 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 (IllegalStateException e) { | 
|             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); | 
|         } finally { | 
|             reader.setLenient(oldLenient); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the Json read from the specified parse tree into an | 
|      * object of the specified type. It is not suitable to use if the specified | 
|      * class is a generic type since it will not have the generic type information | 
|      * because of the Type Erasure feature of Java. Therefore, this method should | 
|      * not be used if the desired type is a generic type. Note that this method | 
|      * works fine if the any of the fields of the specified object are generics, | 
|      * just the object itself should not be a generic type. For the cases when the | 
|      * object is of generic type, invoke {@link #fromJson(JsonElement, Type)}. | 
|      *  | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the root of the parse tree of {@link JsonElement}s from which the | 
|      *            object is to be deserialized | 
|      * @param classOfT | 
|      *            The class of T | 
|      * @return an object of type T from the json. Returns {@code null} if | 
|      *         {@code json} is {@code null}. | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      *             typeOfT | 
|      * @since 1.3 | 
|      */ | 
|     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException { | 
|         Object object = fromJson(json, (Type) classOfT); | 
|         return Primitives.wrap(classOfT).cast(object); | 
|     } | 
|   | 
|     /** | 
|      * This method deserializes the Json read from the specified parse tree into an | 
|      * object of the specified type. This method is useful if the specified object | 
|      * is a generic type. For non-generic objects, use | 
|      * {@link #fromJson(JsonElement, Class)} instead. | 
|      * | 
|      * @param <T> | 
|      *            the type of the desired object | 
|      * @param json | 
|      *            the root of the parse tree of {@link JsonElement}s from which the | 
|      *            object is to be deserialized | 
|      * @param typeOfT | 
|      *            The specific genericized type of src. You can obtain this type by | 
|      *            using the {@link com.google.gson.reflect.TypeToken} class. For | 
|      *            example, to get the type for {@code Collection<Foo>}, you should | 
|      *            use: | 
|      *  | 
|      *            <pre> | 
|      *            Type typeOfT = new TypeToken<Collection<Foo>>() { | 
|      *            }.getType(); | 
|      *            </pre> | 
|      *  | 
|      * @return an object of type T from the json. Returns {@code null} if | 
|      *         {@code json} is {@code null}. | 
|      * @throws JsonSyntaxException | 
|      *             if json is not a valid representation for an object of type | 
|      *             typeOfT | 
|      * @since 1.3 | 
|      */ | 
|     @SuppressWarnings("unchecked") | 
|     public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { | 
|         if (json == null) { | 
|             return null; | 
|         } | 
|         return (T) fromJson(new JsonTreeReader(json), typeOfT); | 
|     } | 
|   | 
|     static class FutureTypeAdapter<T> extends TypeAdapter<T> { | 
|         private TypeAdapter<T> delegate; | 
|   | 
|         public void setDelegate(TypeAdapter<T> typeAdapter) { | 
|             if (delegate != null) { | 
|                 throw new AssertionError(); | 
|             } | 
|             delegate = typeAdapter; | 
|         } | 
|   | 
|         @Override | 
|         public T read(JsonReader in) throws IOException { | 
|             if (delegate == null) { | 
|                 throw new IllegalStateException(); | 
|             } | 
|             return delegate.read(in); | 
|         } | 
|   | 
|         @Override | 
|         public void write(JsonWriter out, T value) throws IOException { | 
|             if (delegate == null) { | 
|                 throw new IllegalStateException(); | 
|             } | 
|             delegate.write(out, value); | 
|         } | 
|     } | 
|   | 
|     @Override | 
|     public String toString() { | 
|         return new StringBuilder("{serializeNulls:").append(serializeNulls).append("factories:").append(factories).append(",instanceCreators:").append(constructorConstructor).append("}").toString(); | 
|     } | 
| } |