/* 
 | 
 * 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(); 
 | 
    } 
 | 
} 
 |