github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/com/google/gson/Gson.java (about)

     1  /*
     2   * Copyright (C) 2008 Google Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   * http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package com.google.gson;
    18  
    19  import java.io.EOFException;
    20  import java.io.IOException;
    21  import java.io.Reader;
    22  import java.io.StringReader;
    23  import java.io.StringWriter;
    24  import java.io.Writer;
    25  import java.lang.reflect.Type;
    26  import java.math.BigDecimal;
    27  import java.math.BigInteger;
    28  import java.util.ArrayList;
    29  import java.util.Collections;
    30  import java.util.HashMap;
    31  import java.util.List;
    32  import java.util.Map;
    33  
    34  import com.google.gson.internal.ConstructorConstructor;
    35  import com.google.gson.internal.Excluder;
    36  import com.google.gson.internal.Primitives;
    37  import com.google.gson.internal.Streams;
    38  import com.google.gson.internal.bind.ArrayTypeAdapter;
    39  import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
    40  import com.google.gson.internal.bind.DateTypeAdapter;
    41  import com.google.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory;
    42  import com.google.gson.internal.bind.JsonTreeReader;
    43  import com.google.gson.internal.bind.JsonTreeWriter;
    44  import com.google.gson.internal.bind.MapTypeAdapterFactory;
    45  import com.google.gson.internal.bind.ObjectTypeAdapter;
    46  import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
    47  import com.google.gson.internal.bind.SqlDateTypeAdapter;
    48  import com.google.gson.internal.bind.TimeTypeAdapter;
    49  import com.google.gson.internal.bind.TypeAdapters;
    50  import com.google.gson.reflect.TypeToken;
    51  import com.google.gson.stream.JsonReader;
    52  import com.google.gson.stream.JsonToken;
    53  import com.google.gson.stream.JsonWriter;
    54  import com.google.gson.stream.MalformedJsonException;
    55  
    56  /**
    57   * This is the main class for using Gson. Gson is typically used by first constructing a
    58   * Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
    59   * methods on it.
    60   *
    61   * <p>You can create a Gson instance by invoking {@code new Gson()} if the default configuration
    62   * is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various
    63   * configuration options such as versioning support, pretty printing, custom
    64   * {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.</p>
    65   *
    66   * <p>Here is an example of how Gson is used for a simple Class:
    67   *
    68   * <pre>
    69   * Gson gson = new Gson(); // Or use new GsonBuilder().create();
    70   * MyType target = new MyType();
    71   * String json = gson.toJson(target); // serializes target to Json
    72   * MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
    73   * </pre></p>
    74   *
    75   * <p>If the object that your are serializing/deserializing is a {@code ParameterizedType}
    76   * (i.e. contains at least one type parameter and may be an array) then you must use the
    77   * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method.  Here is an
    78   * example for serializing and deserialing a {@code ParameterizedType}:
    79   *
    80   * <pre>
    81   * Type listType = new TypeToken&lt;List&lt;String&gt;&gt;() {}.getType();
    82   * List&lt;String&gt; target = new LinkedList&lt;String&gt;();
    83   * target.add("blah");
    84   *
    85   * Gson gson = new Gson();
    86   * String json = gson.toJson(target, listType);
    87   * List&lt;String&gt; target2 = gson.fromJson(json, listType);
    88   * </pre></p>
    89   *
    90   * <p>See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson User Guide</a>
    91   * for a more complete set of examples.</p>
    92   *
    93   * @see TypeToken
    94   *
    95   * @author Inderjeet Singh
    96   * @author Joel Leitch
    97   * @author Jesse Wilson
    98   */
    99  public final class Gson {
   100    static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
   101  
   102    private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
   103  
   104    /**
   105     * This thread local guards against reentrant calls to getAdapter(). In
   106     * certain object graphs, creating an adapter for a type may recursively
   107     * require an adapter for the same type! Without intervention, the recursive
   108     * lookup would stack overflow. We cheat by returning a proxy type adapter.
   109     * The proxy is wired up once the initial adapter has been created.
   110     */
   111    private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
   112        = new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
   113  
   114    private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache
   115        = Collections.synchronizedMap(new HashMap<TypeToken<?>, TypeAdapter<?>>());
   116  
   117    private final List<TypeAdapterFactory> factories;
   118    private final ConstructorConstructor constructorConstructor;
   119  
   120    private final boolean serializeNulls;
   121    private final boolean htmlSafe;
   122    private final boolean generateNonExecutableJson;
   123    private final boolean prettyPrinting;
   124  
   125    final JsonDeserializationContext deserializationContext = new JsonDeserializationContext() {
   126      @SuppressWarnings("unchecked")
   127  	public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
   128        return (T) fromJson(json, typeOfT);
   129      }
   130    };
   131  
   132    final JsonSerializationContext serializationContext = new JsonSerializationContext() {
   133      public JsonElement serialize(Object src) {
   134        return toJsonTree(src);
   135      }
   136      public JsonElement serialize(Object src, Type typeOfSrc) {
   137        return toJsonTree(src, typeOfSrc);
   138      }
   139    };
   140  
   141    /**
   142     * Constructs a Gson object with default configuration. The default configuration has the
   143     * following settings:
   144     * <ul>
   145     *   <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
   146     *   means that all the unneeded white-space is removed. You can change this behavior with
   147     *   {@link GsonBuilder#setPrettyPrinting()}. </li>
   148     *   <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are
   149     *   kept as is since an array is an ordered list. Moreover, if a field is not null, but its
   150     *   generated JSON is empty, the field is kept. You can configure Gson to serialize null values
   151     *   by setting {@link GsonBuilder#serializeNulls()}.</li>
   152     *   <li>Gson provides default serialization and deserialization for Enums, {@link Map},
   153     *   {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date},
   154     *   {@link BigDecimal}, and {@link BigInteger} classes. If you would prefer
   155     *   to change the default representation, you can do so by registering a type adapter through
   156     *   {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
   157     *   <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
   158     *   ignores the millisecond portion of the date during serialization. You can change
   159     *   this by invoking {@link GsonBuilder#setDateFormat(int)} or
   160     *   {@link GsonBuilder#setDateFormat(String)}. </li>
   161     *   <li>By default, Gson ignores the {@link com.google.gson.annotations.Expose} annotation.
   162     *   You can enable Gson to serialize/deserialize only those fields marked with this annotation
   163     *   through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}. </li>
   164     *   <li>By default, Gson ignores the {@link com.google.gson.annotations.Since} annotation. You
   165     *   can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.</li>
   166     *   <li>The default field naming policy for the output Json is same as in Java. So, a Java class
   167     *   field <code>versionNumber</code> will be output as <code>&quot;versionNumber&quot;</code> in
   168     *   Json. The same rules are applied for mapping incoming Json to the Java classes. You can
   169     *   change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.</li>
   170     *   <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
   171     *   consideration for serialization and deserialization. You can change this behavior through
   172     *   {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li>
   173     * </ul>
   174     */
   175    public Gson() {
   176      this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
   177          Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
   178          true, false, false, LongSerializationPolicy.DEFAULT,
   179          Collections.<TypeAdapterFactory>emptyList());
   180    }
   181  
   182    Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
   183        final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
   184        boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
   185        boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
   186        LongSerializationPolicy longSerializationPolicy,
   187        List<TypeAdapterFactory> typeAdapterFactories) {
   188      this.constructorConstructor = new ConstructorConstructor(instanceCreators);
   189      this.serializeNulls = serializeNulls;
   190      this.generateNonExecutableJson = generateNonExecutableGson;
   191      this.htmlSafe = htmlSafe;
   192      this.prettyPrinting = prettyPrinting;
   193  
   194      List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
   195  
   196      // built-in type adapters that cannot be overridden
   197      factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
   198      factories.add(ObjectTypeAdapter.FACTORY);
   199  
   200      // the excluder must precede all adapters that handle user-defined types
   201      factories.add(excluder);
   202  
   203      // user's type adapters
   204      factories.addAll(typeAdapterFactories);
   205  
   206      // type adapters for basic platform types
   207      factories.add(TypeAdapters.STRING_FACTORY);
   208      factories.add(TypeAdapters.INTEGER_FACTORY);
   209      factories.add(TypeAdapters.BOOLEAN_FACTORY);
   210      factories.add(TypeAdapters.BYTE_FACTORY);
   211      factories.add(TypeAdapters.SHORT_FACTORY);
   212      factories.add(TypeAdapters.newFactory(long.class, Long.class,
   213              longAdapter(longSerializationPolicy)));
   214      factories.add(TypeAdapters.newFactory(double.class, Double.class,
   215              doubleAdapter(serializeSpecialFloatingPointValues)));
   216      factories.add(TypeAdapters.newFactory(float.class, Float.class,
   217              floatAdapter(serializeSpecialFloatingPointValues)));
   218      factories.add(TypeAdapters.NUMBER_FACTORY);
   219      factories.add(TypeAdapters.CHARACTER_FACTORY);
   220      factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
   221      factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
   222      factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
   223      factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
   224      factories.add(TypeAdapters.URL_FACTORY);
   225      factories.add(TypeAdapters.URI_FACTORY);
   226      factories.add(TypeAdapters.UUID_FACTORY);
   227      factories.add(TypeAdapters.LOCALE_FACTORY);
   228      factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
   229      factories.add(TypeAdapters.BIT_SET_FACTORY);
   230      factories.add(DateTypeAdapter.FACTORY);
   231      factories.add(TypeAdapters.CALENDAR_FACTORY);
   232      factories.add(TimeTypeAdapter.FACTORY);
   233      factories.add(SqlDateTypeAdapter.FACTORY);
   234      factories.add(TypeAdapters.TIMESTAMP_FACTORY);
   235      factories.add(ArrayTypeAdapter.FACTORY);
   236      factories.add(TypeAdapters.CLASS_FACTORY);
   237  
   238      // type adapters for composite and user-defined types
   239      factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
   240      factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
   241      factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
   242      factories.add(TypeAdapters.ENUM_FACTORY);
   243      factories.add(new ReflectiveTypeAdapterFactory(
   244          constructorConstructor, fieldNamingPolicy, excluder));
   245  
   246      this.factories = Collections.unmodifiableList(factories);
   247    }
   248  
   249    private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) {
   250      if (serializeSpecialFloatingPointValues) {
   251        return TypeAdapters.DOUBLE;
   252      }
   253      return new TypeAdapter<Number>() {
   254        @Override public Double read(JsonReader in) throws IOException {
   255          if (in.peek() == JsonToken.NULL) {
   256            in.nextNull();
   257            return null;
   258          }
   259          return in.nextDouble();
   260        }
   261        @Override public void write(JsonWriter out, Number value) throws IOException {
   262          if (value == null) {
   263            out.nullValue();
   264            return;
   265          }
   266          double doubleValue = value.doubleValue();
   267          checkValidFloatingPoint(doubleValue);
   268          out.value(value);
   269        }
   270      };
   271    }
   272  
   273    private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) {
   274      if (serializeSpecialFloatingPointValues) {
   275        return TypeAdapters.FLOAT;
   276      }
   277      return new TypeAdapter<Number>() {
   278        @Override public Float read(JsonReader in) throws IOException {
   279          if (in.peek() == JsonToken.NULL) {
   280            in.nextNull();
   281            return null;
   282          }
   283          return (float) in.nextDouble();
   284        }
   285        @Override public void write(JsonWriter out, Number value) throws IOException {
   286          if (value == null) {
   287            out.nullValue();
   288            return;
   289          }
   290          float floatValue = value.floatValue();
   291          checkValidFloatingPoint(floatValue);
   292          out.value(value);
   293        }
   294      };
   295    }
   296  
   297    private void checkValidFloatingPoint(double value) {
   298      if (Double.isNaN(value) || Double.isInfinite(value)) {
   299        throw new IllegalArgumentException(value
   300            + " is not a valid double value as per JSON specification. To override this"
   301            + " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.");
   302      }
   303    }
   304  
   305    private TypeAdapter<Number> longAdapter(LongSerializationPolicy longSerializationPolicy) {
   306      if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
   307        return TypeAdapters.LONG;
   308      }
   309      return new TypeAdapter<Number>() {
   310        @Override public Number read(JsonReader in) throws IOException {
   311          if (in.peek() == JsonToken.NULL) {
   312            in.nextNull();
   313            return null;
   314          }
   315          return in.nextLong();
   316        }
   317        @Override public void write(JsonWriter out, Number value) throws IOException {
   318          if (value == null) {
   319            out.nullValue();
   320            return;
   321          }
   322          out.value(value.toString());
   323        }
   324      };
   325    }
   326  
   327    /**
   328     * Returns the type adapter for {@code} type.
   329     *
   330     * @throws IllegalArgumentException if this GSON cannot serialize and
   331     *     deserialize {@code type}.
   332     */
   333    @SuppressWarnings("unchecked")
   334    public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
   335      TypeAdapter<?> cached = typeTokenCache.get(type);
   336      if (cached != null) {
   337        return (TypeAdapter<T>) cached;
   338      }
   339  
   340      Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
   341      boolean requiresThreadLocalCleanup = false;
   342      if (threadCalls == null) {
   343        threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
   344        calls.set(threadCalls);
   345        requiresThreadLocalCleanup = true;
   346      }
   347  
   348      // the key and value type parameters always agree
   349      FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
   350      if (ongoingCall != null) {
   351        return ongoingCall;
   352      }
   353  
   354      try {
   355        FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
   356        threadCalls.put(type, call);
   357  
   358        for (TypeAdapterFactory factory : factories) {
   359          TypeAdapter<T> candidate = factory.create(this, type);
   360          if (candidate != null) {
   361            call.setDelegate(candidate);
   362            typeTokenCache.put(type, candidate);
   363            return candidate;
   364          }
   365        }
   366        throw new IllegalArgumentException("GSON cannot handle " + type);
   367      } finally {
   368        threadCalls.remove(type);
   369  
   370        if (requiresThreadLocalCleanup) {
   371          calls.remove();
   372        }
   373      }
   374    }
   375  
   376    /**
   377     * This method is used to get an alternate type adapter for the specified type. This is used
   378     * to access a type adapter that is overridden by a {@link TypeAdapterFactory} that you
   379     * may have registered. This features is typically used when you want to register a type
   380     * adapter that does a little bit of work but then delegates further processing to the Gson
   381     * default type adapter. Here is an example:
   382     * <p>Let's say we want to write a type adapter that counts the number of objects being read
   383     *  from or written to JSON. We can achieve this by writing a type adapter factory that uses
   384     *  the <code>getDelegateAdapter</code> method:
   385     *  <pre> {@code
   386     *  class StatsTypeAdapterFactory implements TypeAdapterFactory {
   387     *    public int numReads = 0;
   388     *    public int numWrites = 0;
   389     *    public &lt;T&gt; TypeAdapter&lt;T&gt; create(Gson gson, TypeToken&lt;T&gt; type) {
   390     *      final TypeAdapter&lt;T&gt; delegate = gson.getDelegateAdapter(this, type);
   391     *      return new TypeAdapter&lt;T&gt;() {
   392     *        public void write(JsonWriter out, T value) throws IOException {
   393     *          ++numWrites;
   394     *          delegate.write(out, value);
   395     *        }
   396     *        public T read(JsonReader in) throws IOException {
   397     *          ++numReads;
   398     *          return delegate.read(in);
   399     *        }
   400     *      };
   401     *    }
   402     *  }
   403     *  } </pre>
   404     *  This factory can now be used like this:
   405     *  <pre> {@code
   406     *  StatsTypeAdapterFactory stats = new StatsTypeAdapterFactory();
   407     *  Gson gson = new GsonBuilder().registerTypeAdapterFactory(stats).create();
   408     *  // Call gson.toJson() and fromJson methods on objects
   409     *  System.out.println("Num JSON reads" + stats.numReads);
   410     *  System.out.println("Num JSON writes" + stats.numWrites);
   411     *  }</pre>
   412     *  Note that since you can not override type adapter factories for String and Java primitive
   413     *  types, our stats factory will not count the number of String or primitives that will be
   414     *  read or written.
   415     * @param skipPast The type adapter factory that needs to be skipped while searching for
   416     *   a matching type adapter. In most cases, you should just pass <i>this</i> (the type adapter
   417     *   factory from where {@link #getDelegateAdapter} method is being invoked).
   418     * @param type Type for which the delegate adapter is being searched for.
   419     *
   420     * @since 2.2
   421     */
   422    public <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type) {
   423      boolean skipPastFound = false;
   424      // Skip past if and only if the specified factory is present in the factories.
   425      // This is useful because the factories created through JsonAdapter annotations are not
   426      // registered in this list.
   427      if (!factories.contains(skipPast)) skipPastFound = true;
   428  
   429      for (TypeAdapterFactory factory : factories) {
   430        if (!skipPastFound) {
   431          if (factory == skipPast) {
   432            skipPastFound = true;
   433          }
   434          continue;
   435        }
   436  
   437        TypeAdapter<T> candidate = factory.create(this, type);
   438        if (candidate != null) {
   439          return candidate;
   440        }
   441      }
   442      throw new IllegalArgumentException("GSON cannot serialize " + type);
   443    }
   444  
   445    /**
   446     * Returns the type adapter for {@code} type.
   447     *
   448     * @throws IllegalArgumentException if this GSON cannot serialize and
   449     *     deserialize {@code type}.
   450     */
   451    public <T> TypeAdapter<T> getAdapter(Class<T> type) {
   452      return getAdapter(TypeToken.get(type));
   453    }
   454  
   455    /**
   456     * This method serializes the specified object into its equivalent representation as a tree of
   457     * {@link JsonElement}s. This method should be used when the specified object is not a generic
   458     * type. This method uses {@link Class#getClass()} to get the type for the specified object, but
   459     * the {@code getClass()} loses the generic type information because of the Type Erasure feature
   460     * of Java. Note that this method works fine if the any of the object fields are of generic type,
   461     * just the object itself should not be of a generic type. If the object is of generic type, use
   462     * {@link #toJsonTree(Object, Type)} instead.
   463     *
   464     * @param src the object for which Json representation is to be created setting for Gson
   465     * @return Json representation of {@code src}.
   466     * @since 1.4
   467     */
   468    public JsonElement toJsonTree(Object src) {
   469      if (src == null) {
   470        return JsonNull.INSTANCE;
   471      }
   472      return toJsonTree(src, src.getClass());
   473    }
   474  
   475    /**
   476     * This method serializes the specified object, including those of generic types, into its
   477     * equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
   478     * specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
   479     * instead.
   480     *
   481     * @param src the object for which JSON representation is to be created
   482     * @param typeOfSrc The specific genericized type of src. You can obtain
   483     * this type by using the {@link TypeToken} class. For example,
   484     * to get the type for {@code Collection<Foo>}, you should use:
   485     * <pre>
   486     * Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   487     * </pre>
   488     * @return Json representation of {@code src}
   489     * @since 1.4
   490     */
   491    public JsonElement toJsonTree(Object src, Type typeOfSrc) {
   492      JsonTreeWriter writer = new JsonTreeWriter();
   493      toJson(src, typeOfSrc, writer);
   494      return writer.get();
   495    }
   496  
   497    /**
   498     * This method serializes the specified object into its equivalent Json representation.
   499     * This method should be used when the specified object is not a generic type. This method uses
   500     * {@link Class#getClass()} to get the type for the specified object, but the
   501     * {@code getClass()} loses the generic type information because of the Type Erasure feature
   502     * of Java. Note that this method works fine if the any of the object fields are of generic type,
   503     * just the object itself should not be of a generic type. If the object is of generic type, use
   504     * {@link #toJson(Object, Type)} instead. If you want to write out the object to a
   505     * {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
   506     *
   507     * @param src the object for which Json representation is to be created setting for Gson
   508     * @return Json representation of {@code src}.
   509     */
   510    public String toJson(Object src) {
   511      if (src == null) {
   512        return toJson(JsonNull.INSTANCE);
   513      }
   514      return toJson(src, src.getClass());
   515    }
   516  
   517    /**
   518     * This method serializes the specified object, including those of generic types, into its
   519     * equivalent Json representation. This method must be used if the specified object is a generic
   520     * type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
   521     * the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
   522     *
   523     * @param src the object for which JSON representation is to be created
   524     * @param typeOfSrc The specific genericized type of src. You can obtain
   525     * this type by using the {@link TypeToken} class. For example,
   526     * to get the type for {@code Collection<Foo>}, you should use:
   527     * <pre>
   528     * Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   529     * </pre>
   530     * @return Json representation of {@code src}
   531     */
   532    public String toJson(Object src, Type typeOfSrc) {
   533      StringWriter writer = new StringWriter();
   534      toJson(src, typeOfSrc, writer);
   535      return writer.toString();
   536    }
   537  
   538    /**
   539     * This method serializes the specified object into its equivalent Json representation.
   540     * This method should be used when the specified object is not a generic type. This method uses
   541     * {@link Class#getClass()} to get the type for the specified object, but the
   542     * {@code getClass()} loses the generic type information because of the Type Erasure feature
   543     * of Java. Note that this method works fine if the any of the object fields are of generic type,
   544     * just the object itself should not be of a generic type. If the object is of generic type, use
   545     * {@link #toJson(Object, Type, Appendable)} instead.
   546     *
   547     * @param src the object for which Json representation is to be created setting for Gson
   548     * @param writer Writer to which the Json representation needs to be written
   549     * @throws JsonIOException if there was a problem writing to the writer
   550     * @since 1.2
   551     */
   552    public void toJson(Object src, Appendable writer) throws JsonIOException {
   553      if (src != null) {
   554        toJson(src, src.getClass(), writer);
   555      } else {
   556        toJson(JsonNull.INSTANCE, writer);
   557      }
   558    }
   559  
   560    /**
   561     * This method serializes the specified object, including those of generic types, into its
   562     * equivalent Json representation. This method must be used if the specified object is a generic
   563     * type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
   564     *
   565     * @param src the object for which JSON representation is to be created
   566     * @param typeOfSrc The specific genericized type of src. You can obtain
   567     * this type by using the {@link TypeToken} class. For example,
   568     * to get the type for {@code Collection<Foo>}, you should use:
   569     * <pre>
   570     * Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   571     * </pre>
   572     * @param writer Writer to which the Json representation of src needs to be written.
   573     * @throws JsonIOException if there was a problem writing to the writer
   574     * @since 1.2
   575     */
   576    public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
   577      try {
   578        JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
   579        toJson(src, typeOfSrc, jsonWriter);
   580      } catch (IOException e) {
   581        throw new JsonIOException(e);
   582      }
   583    }
   584  
   585    /**
   586     * Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
   587     * {@code writer}.
   588     * @throws JsonIOException if there was a problem writing to the writer
   589     */
   590    @SuppressWarnings("unchecked")
   591    public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
   592      TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
   593      boolean oldLenient = writer.isLenient();
   594      writer.setLenient(true);
   595      boolean oldHtmlSafe = writer.isHtmlSafe();
   596      writer.setHtmlSafe(htmlSafe);
   597      boolean oldSerializeNulls = writer.getSerializeNulls();
   598      writer.setSerializeNulls(serializeNulls);
   599      try {
   600        ((TypeAdapter<Object>) adapter).write(writer, src);
   601      } catch (IOException e) {
   602        throw new JsonIOException(e);
   603      } finally {
   604        writer.setLenient(oldLenient);
   605        writer.setHtmlSafe(oldHtmlSafe);
   606        writer.setSerializeNulls(oldSerializeNulls);
   607      }
   608    }
   609  
   610    /**
   611     * Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
   612     *
   613     * @param jsonElement root of a tree of {@link JsonElement}s
   614     * @return JSON String representation of the tree
   615     * @since 1.4
   616     */
   617    public String toJson(JsonElement jsonElement) {
   618      StringWriter writer = new StringWriter();
   619      toJson(jsonElement, writer);
   620      return writer.toString();
   621    }
   622  
   623    /**
   624     * Writes out the equivalent JSON for a tree of {@link JsonElement}s.
   625     *
   626     * @param jsonElement root of a tree of {@link JsonElement}s
   627     * @param writer Writer to which the Json representation needs to be written
   628     * @throws JsonIOException if there was a problem writing to the writer
   629     * @since 1.4
   630     */
   631    public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
   632      try {
   633        JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
   634        toJson(jsonElement, jsonWriter);
   635      } catch (IOException e) {
   636        throw new RuntimeException(e);
   637      }
   638    }
   639  
   640    /**
   641     * Returns a new JSON writer configured for this GSON and with the non-execute
   642     * prefix if that is configured.
   643     */
   644    private JsonWriter newJsonWriter(Writer writer) throws IOException {
   645      if (generateNonExecutableJson) {
   646        writer.write(JSON_NON_EXECUTABLE_PREFIX);
   647      }
   648      JsonWriter jsonWriter = new JsonWriter(writer);
   649      if (prettyPrinting) {
   650        jsonWriter.setIndent("  ");
   651      }
   652      jsonWriter.setSerializeNulls(serializeNulls);
   653      return jsonWriter;
   654    }
   655  
   656    /**
   657     * Writes the JSON for {@code jsonElement} to {@code writer}.
   658     * @throws JsonIOException if there was a problem writing to the writer
   659     */
   660    public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
   661      boolean oldLenient = writer.isLenient();
   662      writer.setLenient(true);
   663      boolean oldHtmlSafe = writer.isHtmlSafe();
   664      writer.setHtmlSafe(htmlSafe);
   665      boolean oldSerializeNulls = writer.getSerializeNulls();
   666      writer.setSerializeNulls(serializeNulls);
   667      try {
   668        Streams.write(jsonElement, writer);
   669      } catch (IOException e) {
   670        throw new JsonIOException(e);
   671      } finally {
   672        writer.setLenient(oldLenient);
   673        writer.setHtmlSafe(oldHtmlSafe);
   674        writer.setSerializeNulls(oldSerializeNulls);
   675      }
   676    }
   677  
   678    /**
   679     * This method deserializes the specified Json into an object of the specified class. It is not
   680     * suitable to use if the specified class is a generic type since it will not have the generic
   681     * type information because of the Type Erasure feature of Java. Therefore, this method should not
   682     * be used if the desired type is a generic type. Note that this method works fine if the any of
   683     * the fields of the specified object are generics, just the object itself should not be a
   684     * generic type. For the cases when the object is of generic type, invoke
   685     * {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
   686     * a String, use {@link #fromJson(Reader, Class)} instead.
   687     *
   688     * @param <T> the type of the desired object
   689     * @param json the string from which the object is to be deserialized
   690     * @param classOfT the class of T
   691     * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
   692     * @throws JsonSyntaxException if json is not a valid representation for an object of type
   693     * classOfT
   694     */
   695    public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
   696      Object object = fromJson(json, (Type) classOfT);
   697      return Primitives.wrap(classOfT).cast(object);
   698    }
   699  
   700    /**
   701     * This method deserializes the specified Json into an object of the specified type. This method
   702     * is useful if the specified object is a generic type. For non-generic objects, use
   703     * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
   704     * a String, use {@link #fromJson(Reader, Type)} instead.
   705     *
   706     * @param <T> the type of the desired object
   707     * @param json the string from which the object is to be deserialized
   708     * @param typeOfT The specific genericized type of src. You can obtain this type by using the
   709     * {@link TypeToken} class. For example, to get the type for
   710     * {@code Collection<Foo>}, you should use:
   711     * <pre>
   712     * Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   713     * </pre>
   714     * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
   715     * @throws JsonParseException if json is not a valid representation for an object of type typeOfT
   716     * @throws JsonSyntaxException if json is not a valid representation for an object of type
   717     */
   718    @SuppressWarnings("unchecked")
   719    public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
   720      if (json == null) {
   721        return null;
   722      }
   723      StringReader reader = new StringReader(json);
   724      T target = (T) fromJson(reader, typeOfT);
   725      return target;
   726    }
   727  
   728    /**
   729     * This method deserializes the Json read from the specified reader into an object of the
   730     * specified class. It is not suitable to use if the specified class is a generic type since it
   731     * will not have the generic type information because of the Type Erasure feature of Java.
   732     * Therefore, this method should not be used if the desired type is a generic type. Note that
   733     * this method works fine if the any of the fields of the specified object are generics, just the
   734     * object itself should not be a generic type. For the cases when the object is of generic type,
   735     * invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
   736     * {@link Reader}, use {@link #fromJson(String, Class)} instead.
   737     *
   738     * @param <T> the type of the desired object
   739     * @param json the reader producing the Json from which the object is to be deserialized.
   740     * @param classOfT the class of T
   741     * @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF.
   742     * @throws JsonIOException if there was a problem reading from the Reader
   743     * @throws JsonSyntaxException if json is not a valid representation for an object of type
   744     * @since 1.2
   745     */
   746    public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
   747      JsonReader jsonReader = new JsonReader(json);
   748      Object object = fromJson(jsonReader, classOfT);
   749      assertFullConsumption(object, jsonReader);
   750      return Primitives.wrap(classOfT).cast(object);
   751    }
   752  
   753    /**
   754     * This method deserializes the Json read from the specified reader into an object of the
   755     * specified type. This method is useful if the specified object is a generic type. For
   756     * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
   757     * String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead.
   758     *
   759     * @param <T> the type of the desired object
   760     * @param json the reader producing Json from which the object is to be deserialized
   761     * @param typeOfT The specific genericized type of src. You can obtain this type by using the
   762     * {@link TypeToken} class. For example, to get the type for
   763     * {@code Collection<Foo>}, you should use:
   764     * <pre>
   765     * Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   766     * </pre>
   767     * @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF.
   768     * @throws JsonIOException if there was a problem reading from the Reader
   769     * @throws JsonSyntaxException if json is not a valid representation for an object of type
   770     * @since 1.2
   771     */
   772    @SuppressWarnings("unchecked")
   773    public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
   774      JsonReader jsonReader = new JsonReader(json);
   775      T object = (T) fromJson(jsonReader, typeOfT);
   776      assertFullConsumption(object, jsonReader);
   777      return object;
   778    }
   779  
   780    private static void assertFullConsumption(Object obj, JsonReader reader) {
   781      try {
   782        if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
   783          throw new JsonIOException("JSON document was not fully consumed.");
   784        }
   785      } catch (MalformedJsonException e) {
   786        throw new JsonSyntaxException(e);
   787      } catch (IOException e) {
   788        throw new JsonIOException(e);
   789      }
   790    }
   791  
   792    /**
   793     * Reads the next JSON value from {@code reader} and convert it to an object
   794     * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
   795     * Since Type is not parameterized by T, this method is type unsafe and should be used carefully
   796     *
   797     * @throws JsonIOException if there was a problem writing to the Reader
   798     * @throws JsonSyntaxException if json is not a valid representation for an object of type
   799     */
   800    @SuppressWarnings("unchecked")
   801    public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
   802      boolean isEmpty = true;
   803      boolean oldLenient = reader.isLenient();
   804      reader.setLenient(true);
   805      try {
   806        reader.peek();
   807        isEmpty = false;
   808        TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
   809        TypeAdapter<T> typeAdapter = getAdapter(typeToken);
   810        T object = typeAdapter.read(reader);
   811        return object;
   812      } catch (EOFException e) {
   813        /*
   814         * For compatibility with JSON 1.5 and earlier, we return null for empty
   815         * documents instead of throwing.
   816         */
   817        if (isEmpty) {
   818          return null;
   819        }
   820        throw new JsonSyntaxException(e);
   821      } catch (IllegalStateException e) {
   822        throw new JsonSyntaxException(e);
   823      } catch (IOException e) {
   824        // TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
   825        throw new JsonSyntaxException(e);
   826      } finally {
   827        reader.setLenient(oldLenient);
   828      }
   829    }
   830  
   831    /**
   832     * This method deserializes the Json read from the specified parse tree into an object of the
   833     * specified type. It is not suitable to use if the specified class is a generic type since it
   834     * will not have the generic type information because of the Type Erasure feature of Java.
   835     * Therefore, this method should not be used if the desired type is a generic type. Note that
   836     * this method works fine if the any of the fields of the specified object are generics, just the
   837     * object itself should not be a generic type. For the cases when the object is of generic type,
   838     * invoke {@link #fromJson(JsonElement, Type)}.
   839     * @param <T> the type of the desired object
   840     * @param json the root of the parse tree of {@link JsonElement}s from which the object is to
   841     * be deserialized
   842     * @param classOfT The class of T
   843     * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
   844     * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
   845     * @since 1.3
   846     */
   847    public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
   848      Object object = fromJson(json, (Type) classOfT);
   849      return Primitives.wrap(classOfT).cast(object);
   850    }
   851  
   852    /**
   853     * This method deserializes the Json read from the specified parse tree into an object of the
   854     * specified type. This method is useful if the specified object is a generic type. For
   855     * non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
   856     *
   857     * @param <T> the type of the desired object
   858     * @param json the root of the parse tree of {@link JsonElement}s from which the object is to
   859     * be deserialized
   860     * @param typeOfT The specific genericized type of src. You can obtain this type by using the
   861     * {@link TypeToken} class. For example, to get the type for
   862     * {@code Collection<Foo>}, you should use:
   863     * <pre>
   864     * Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
   865     * </pre>
   866     * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
   867     * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
   868     * @since 1.3
   869     */
   870    @SuppressWarnings("unchecked")
   871    public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
   872      if (json == null) {
   873        return null;
   874      }
   875      return (T) fromJson(new JsonTreeReader(json), typeOfT);
   876    }
   877  
   878    static class FutureTypeAdapter<T> extends TypeAdapter<T> {
   879      private TypeAdapter<T> delegate;
   880  
   881      public void setDelegate(TypeAdapter<T> typeAdapter) {
   882        if (delegate != null) {
   883          throw new AssertionError();
   884        }
   885        delegate = typeAdapter;
   886      }
   887  
   888      @Override public T read(JsonReader in) throws IOException {
   889        if (delegate == null) {
   890          throw new IllegalStateException();
   891        }
   892        return delegate.read(in);
   893      }
   894  
   895      @Override public void write(JsonWriter out, T value) throws IOException {
   896        if (delegate == null) {
   897          throw new IllegalStateException();
   898        }
   899        delegate.write(out, value);
   900      }
   901    }
   902  
   903    @Override
   904    public String toString() {
   905      return new StringBuilder("{serializeNulls:")
   906          .append(serializeNulls)
   907          .append("factories:").append(factories)
   908          .append(",instanceCreators:").append(constructorConstructor)
   909          .append("}")
   910          .toString();
   911    }
   912  }