github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/com/google/gson/GsonBuilder.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.lang.reflect.Type;
    20  import java.sql.Timestamp;
    21  import java.text.DateFormat;
    22  import java.util.ArrayList;
    23  import java.util.Collections;
    24  import java.util.Date;
    25  import java.util.HashMap;
    26  import java.util.List;
    27  import java.util.Map;
    28  
    29  import com.google.gson.internal.$Gson$Preconditions;
    30  import com.google.gson.internal.Excluder;
    31  import com.google.gson.internal.bind.TypeAdapters;
    32  import com.google.gson.reflect.TypeToken;
    33  
    34  /**
    35   * <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
    36   * options other than the default. For {@link Gson} with default configuration, it is simpler to
    37   * use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
    38   * various configuration methods, and finally calling create.</p>
    39   *
    40   * <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
    41   * instance:
    42   *
    43   * <pre>
    44   * Gson gson = new GsonBuilder()
    45   *     .registerTypeAdapter(Id.class, new IdTypeAdapter())
    46   *     .enableComplexMapKeySerialization()
    47   *     .serializeNulls()
    48   *     .setDateFormat(DateFormat.LONG)
    49   *     .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
    50   *     .setPrettyPrinting()
    51   *     .setVersion(1.0)
    52   *     .create();
    53   * </pre></p>
    54   *
    55   * <p>NOTES:
    56   * <ul>
    57   * <li> the order of invocation of configuration methods does not matter.</li>
    58   * <li> The default serialization of {@link Date} and its subclasses in Gson does
    59   *  not contain time-zone information. So, if you are using date/time instances,
    60   *  use {@code GsonBuilder} and its {@code setDateFormat} methods.</li>
    61   *  </ul>
    62   * </p>
    63   *
    64   * @author Inderjeet Singh
    65   * @author Joel Leitch
    66   * @author Jesse Wilson
    67   */
    68  public final class GsonBuilder {
    69    private Excluder excluder = Excluder.DEFAULT;
    70    private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
    71    private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
    72    private final Map<Type, InstanceCreator<?>> instanceCreators
    73        = new HashMap<Type, InstanceCreator<?>>();
    74    private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
    75    /** tree-style hierarchy factories. These come after factories for backwards compatibility. */
    76    private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>();
    77    private boolean serializeNulls;
    78    private String datePattern;
    79    private int dateStyle = DateFormat.DEFAULT;
    80    private int timeStyle = DateFormat.DEFAULT;
    81    private boolean complexMapKeySerialization;
    82    private boolean serializeSpecialFloatingPointValues;
    83    private boolean escapeHtmlChars = true;
    84    private boolean prettyPrinting;
    85    private boolean generateNonExecutableJson;
    86  
    87    /**
    88     * Creates a GsonBuilder instance that can be used to build Gson with various configuration
    89     * settings. GsonBuilder follows the builder pattern, and it is typically used by first
    90     * invoking various configuration methods to set desired options, and finally calling
    91     * {@link #create()}.
    92     */
    93    public GsonBuilder() {
    94    }
    95  
    96    /**
    97     * Configures Gson to enable versioning support.
    98     *
    99     * @param ignoreVersionsAfter any field or type marked with a version higher than this value
   100     * are ignored during serialization or deserialization.
   101     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   102     */
   103    public GsonBuilder setVersion(double ignoreVersionsAfter) {
   104      excluder = excluder.withVersion(ignoreVersionsAfter);
   105      return this;
   106    }
   107  
   108    /**
   109     * Configures Gson to excludes all class fields that have the specified modifiers. By default,
   110     * Gson will exclude all fields marked transient or static. This method will override that
   111     * behavior.
   112     *
   113     * @param modifiers the field modifiers. You must use the modifiers specified in the
   114     * {@link java.lang.reflect.Modifier} class. For example,
   115     * {@link java.lang.reflect.Modifier#TRANSIENT},
   116     * {@link java.lang.reflect.Modifier#STATIC}.
   117     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   118     */
   119    public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
   120      excluder = excluder.withModifiers(modifiers);
   121      return this;
   122    }
   123  
   124    /**
   125     * Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
   126     * special text. This prevents attacks from third-party sites through script sourcing. See
   127     * <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
   128     * for details.
   129     *
   130     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   131     * @since 1.3
   132     */
   133    public GsonBuilder generateNonExecutableJson() {
   134      this.generateNonExecutableJson = true;
   135      return this;
   136    }
   137  
   138    /**
   139     * Configures Gson to exclude all fields from consideration for serialization or deserialization
   140     * that do not have the {@link com.google.gson.annotations.Expose} annotation.
   141     *
   142     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   143     */
   144    public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
   145      excluder = excluder.excludeFieldsWithoutExposeAnnotation();
   146      return this;
   147    }
   148  
   149    /**
   150     * Configure Gson to serialize null fields. By default, Gson omits all fields that are null
   151     * during serialization.
   152     *
   153     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   154     * @since 1.2
   155     */
   156    public GsonBuilder serializeNulls() {
   157      this.serializeNulls = true;
   158      return this;
   159    }
   160  
   161    /**
   162     * Enabling this feature will only change the serialized form if the map key is
   163     * a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON
   164     * form. The default implementation of map serialization uses {@code toString()}
   165     * on the key; however, when this is called then one of the following cases
   166     * apply:
   167     *
   168     * <h3>Maps as JSON objects</h3>
   169     * For this case, assume that a type adapter is registered to serialize and
   170     * deserialize some {@code Point} class, which contains an x and y coordinate,
   171     * to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
   172     * then be serialized as a {@link JsonObject}.
   173     *
   174     * <p>Below is an example:
   175     * <pre>  {@code
   176     *   Gson gson = new GsonBuilder()
   177     *       .register(Point.class, new MyPointTypeAdapter())
   178     *       .enableComplexMapKeySerialization()
   179     *       .create();
   180     *
   181     *   Map<Point, String> original = new LinkedHashMap<Point, String>();
   182     *   original.put(new Point(5, 6), "a");
   183     *   original.put(new Point(8, 8), "b");
   184     *   System.out.println(gson.toJson(original, type));
   185     * }</pre>
   186     * The above code prints this JSON object:<pre>  {@code
   187     *   {
   188     *     "(5,6)": "a",
   189     *     "(8,8)": "b"
   190     *   }
   191     * }</pre>
   192     *
   193     * <h3>Maps as JSON arrays</h3>
   194     * For this case, assume that a type adapter was NOT registered for some
   195     * {@code Point} class, but rather the default Gson serialization is applied.
   196     * In this case, some {@code new Point(2,3)} would serialize as {@code
   197     * {"x":2,"y":5}}.
   198     *
   199     * <p>Given the assumption above, a {@code Map<Point, String>} will be
   200     * serialize as an array of arrays (can be viewed as an entry set of pairs).
   201     *
   202     * <p>Below is an example of serializing complex types as JSON arrays:
   203     * <pre> {@code
   204     *   Gson gson = new GsonBuilder()
   205     *       .enableComplexMapKeySerialization()
   206     *       .create();
   207     *
   208     *   Map<Point, String> original = new LinkedHashMap<Point, String>();
   209     *   original.put(new Point(5, 6), "a");
   210     *   original.put(new Point(8, 8), "b");
   211     *   System.out.println(gson.toJson(original, type));
   212     * }
   213     *
   214     * The JSON output would look as follows:
   215     * <pre>   {@code
   216     *   [
   217     *     [
   218     *       {
   219     *         "x": 5,
   220     *         "y": 6
   221     *       },
   222     *       "a"
   223     *     ],
   224     *     [
   225     *       {
   226     *         "x": 8,
   227     *         "y": 8
   228     *       },
   229     *       "b"
   230     *     ]
   231     *   ]
   232     * }</pre>
   233     *
   234     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   235     * @since 1.7
   236     */
   237    public GsonBuilder enableComplexMapKeySerialization() {
   238      complexMapKeySerialization = true;
   239      return this;
   240    }
   241  
   242    /**
   243     * Configures Gson to exclude inner classes during serialization.
   244     *
   245     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   246     * @since 1.3
   247     */
   248    public GsonBuilder disableInnerClassSerialization() {
   249      excluder = excluder.disableInnerClassSerialization();
   250      return this;
   251    }
   252  
   253    /**
   254     * Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
   255     * objects.
   256     *
   257     * @param serializationPolicy the particular policy to use for serializing longs.
   258     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   259     * @since 1.3
   260     */
   261    public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
   262      this.longSerializationPolicy = serializationPolicy;
   263      return this;
   264    }
   265  
   266    /**
   267     * Configures Gson to apply a specific naming policy to an object's field during serialization
   268     * and deserialization.
   269     *
   270     * @param namingConvention the JSON field naming convention to use for serialization and
   271     * deserialization.
   272     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   273     */
   274    public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
   275      this.fieldNamingPolicy = namingConvention;
   276      return this;
   277    }
   278  
   279    /**
   280     * Configures Gson to apply a specific naming policy strategy to an object's field during
   281     * serialization and deserialization.
   282     *
   283     * @param fieldNamingStrategy the actual naming strategy to apply to the fields
   284     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   285     * @since 1.3
   286     */
   287    public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
   288      this.fieldNamingPolicy = fieldNamingStrategy;
   289      return this;
   290    }
   291  
   292    /**
   293     * Configures Gson to apply a set of exclusion strategies during both serialization and
   294     * deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
   295     * This means that if one of the {@code strategies} suggests that a field (or class) should be
   296     * skipped then that field (or object) is skipped during serializaiton/deserialization.
   297     *
   298     * @param strategies the set of strategy object to apply during object (de)serialization.
   299     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   300     * @since 1.4
   301     */
   302    public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
   303      for (ExclusionStrategy strategy : strategies) {
   304        excluder = excluder.withExclusionStrategy(strategy, true, true);
   305      }
   306      return this;
   307    }
   308  
   309    /**
   310     * Configures Gson to apply the passed in exclusion strategy during serialization.
   311     * If this method is invoked numerous times with different exclusion strategy objects
   312     * then the exclusion strategies that were added will be applied as a disjunction rule.
   313     * This means that if one of the added exclusion strategies suggests that a field (or
   314     * class) should be skipped then that field (or object) is skipped during its
   315     * serialization.
   316     *
   317     * @param strategy an exclusion strategy to apply during serialization.
   318     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   319     * @since 1.7
   320     */
   321    public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
   322      excluder = excluder.withExclusionStrategy(strategy, true, false);
   323      return this;
   324    }
   325  
   326    /**
   327     * Configures Gson to apply the passed in exclusion strategy during deserialization.
   328     * If this method is invoked numerous times with different exclusion strategy objects
   329     * then the exclusion strategies that were added will be applied as a disjunction rule.
   330     * This means that if one of the added exclusion strategies suggests that a field (or
   331     * class) should be skipped then that field (or object) is skipped during its
   332     * deserialization.
   333     *
   334     * @param strategy an exclusion strategy to apply during deserialization.
   335     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   336     * @since 1.7
   337     */
   338    public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
   339      excluder = excluder.withExclusionStrategy(strategy, false, true);
   340      return this;
   341    }
   342  
   343    /**
   344     * Configures Gson to output Json that fits in a page for pretty printing. This option only
   345     * affects Json serialization.
   346     *
   347     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   348     */
   349    public GsonBuilder setPrettyPrinting() {
   350      prettyPrinting = true;
   351      return this;
   352    }
   353  
   354    /**
   355     * By default, Gson escapes HTML characters such as &lt; &gt; etc. Use this option to configure
   356     * Gson to pass-through HTML characters as is.
   357     *
   358     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   359     * @since 1.3
   360     */
   361    public GsonBuilder disableHtmlEscaping() {
   362      this.escapeHtmlChars = false;
   363      return this;
   364    }
   365  
   366    /**
   367     * Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
   368     * call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
   369     * will be used to decide the serialization format.
   370     *
   371     * <p>The date format will be used to serialize and deserialize {@link Date}, {@link
   372     * Timestamp} and {@link java.sql.Date}.
   373     *
   374     * <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
   375     * class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
   376     * valid date and time patterns.</p>
   377     *
   378     * @param pattern the pattern that dates will be serialized/deserialized to/from
   379     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   380     * @since 1.2
   381     */
   382    public GsonBuilder setDateFormat(String pattern) {
   383      // TODO(Joel): Make this fail fast if it is an invalid date format
   384      this.datePattern = pattern;
   385      return this;
   386    }
   387  
   388    /**
   389     * Configures Gson to to serialize {@code Date} objects according to the style value provided.
   390     * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
   391     * invocation will be used to decide the serialization format.
   392     *
   393     * <p>Note that this style value should be one of the predefined constants in the
   394     * {@code DateFormat} class. See the documentation in {@link DateFormat} for more
   395     * information on the valid style constants.</p>
   396     *
   397     * @param style the predefined date style that date objects will be serialized/deserialized
   398     * to/from
   399     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   400     * @since 1.2
   401     */
   402    public GsonBuilder setDateFormat(int style) {
   403      this.dateStyle = style;
   404      this.datePattern = null;
   405      return this;
   406    }
   407  
   408    /**
   409     * Configures Gson to to serialize {@code Date} objects according to the style value provided.
   410     * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
   411     * invocation will be used to decide the serialization format.
   412     *
   413     * <p>Note that this style value should be one of the predefined constants in the
   414     * {@code DateFormat} class. See the documentation in {@link DateFormat} for more
   415     * information on the valid style constants.</p>
   416     *
   417     * @param dateStyle the predefined date style that date objects will be serialized/deserialized
   418     * to/from
   419     * @param timeStyle the predefined style for the time portion of the date objects
   420     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   421     * @since 1.2
   422     */
   423    public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
   424      this.dateStyle = dateStyle;
   425      this.timeStyle = timeStyle;
   426      this.datePattern = null;
   427      return this;
   428    }
   429  
   430    /**
   431     * Configures Gson for custom serialization or deserialization. This method combines the
   432     * registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a
   433     * {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
   434     * all the required interfaces for custom serialization with Gson. If a type adapter was
   435     * previously registered for the specified {@code type}, it is overwritten.
   436     *
   437     * <p>This registers the type specified and no other types: you must manually register related
   438     * types! For example, applications registering {@code boolean.class} should also register {@code
   439     * Boolean.class}.
   440     *
   441     * @param type the type definition for the type adapter being registered
   442     * @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
   443     * {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
   444     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   445     */
   446    @SuppressWarnings({"unchecked", "rawtypes"})
   447    public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
   448      $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
   449          || typeAdapter instanceof JsonDeserializer<?>
   450          || typeAdapter instanceof InstanceCreator<?>
   451          || typeAdapter instanceof TypeAdapter<?>);
   452      if (typeAdapter instanceof InstanceCreator<?>) {
   453        instanceCreators.put(type, (InstanceCreator) typeAdapter);
   454      }
   455      if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
   456        TypeToken<?> typeToken = TypeToken.get(type);
   457        factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
   458      }
   459      if (typeAdapter instanceof TypeAdapter<?>) {
   460        factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
   461      }
   462      return this;
   463    }
   464  
   465    /**
   466     * Register a factory for type adapters. Registering a factory is useful when the type
   467     * adapter needs to be configured based on the type of the field being processed. Gson
   468     * is designed to handle a large number of factories, so you should consider registering
   469     * them to be at par with registering an individual type adapter.
   470     *
   471     * @since 2.1
   472     */
   473    public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
   474      factories.add(factory);
   475      return this;
   476    }
   477  
   478    /**
   479     * Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
   480     * This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and
   481     * a {@link JsonDeserializer}. If a type adapter was previously registered for the specified
   482     * type hierarchy, it is overridden. If a type adapter is registered for a specific type in
   483     * the type hierarchy, it will be invoked instead of the one registered for the type hierarchy.
   484     *
   485     * @param baseType the class definition for the type adapter being registered for the base class
   486     *        or interface
   487     * @param typeAdapter This object must implement at least one of {@link TypeAdapter},
   488     *        {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
   489     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   490     * @since 1.7
   491     */
   492    @SuppressWarnings({"unchecked", "rawtypes"})
   493    public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
   494      $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
   495          || typeAdapter instanceof JsonDeserializer<?>
   496          || typeAdapter instanceof TypeAdapter<?>);
   497      if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
   498        hierarchyFactories.add(0,
   499            TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
   500      }
   501      if (typeAdapter instanceof TypeAdapter<?>) {
   502        factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
   503      }
   504      return this;
   505    }
   506  
   507    /**
   508     * Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
   509     * special double values (NaN, Infinity, -Infinity). However,
   510     * <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
   511     * specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
   512     * values. Moreover, most JavaScript engines will accept these special values in JSON without
   513     * problem. So, at a practical level, it makes sense to accept these values as valid JSON even
   514     * though JSON specification disallows them.
   515     *
   516     * <p>Gson always accepts these special values during deserialization. However, it outputs
   517     * strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
   518     * {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
   519     * {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
   520     * will throw an {@link IllegalArgumentException}. This method provides a way to override the
   521     * default behavior when you know that the JSON receiver will be able to handle these special
   522     * values.
   523     *
   524     * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
   525     * @since 1.3
   526     */
   527    public GsonBuilder serializeSpecialFloatingPointValues() {
   528      this.serializeSpecialFloatingPointValues = true;
   529      return this;
   530    }
   531  
   532    /**
   533     * Creates a {@link Gson} instance based on the current configuration. This method is free of
   534     * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
   535     *
   536     * @return an instance of Gson configured with the options currently set in this builder
   537     */
   538    public Gson create() {
   539      List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
   540      factories.addAll(this.factories);
   541      Collections.reverse(factories);
   542      factories.addAll(this.hierarchyFactories);
   543      addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
   544  
   545      return new Gson(excluder, fieldNamingPolicy, instanceCreators,
   546          serializeNulls, complexMapKeySerialization,
   547          generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
   548          serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
   549    }
   550  
   551    private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
   552        List<TypeAdapterFactory> factories) {
   553      DefaultDateTypeAdapter dateTypeAdapter;
   554      if (datePattern != null && !"".equals(datePattern.trim())) {
   555        dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
   556      } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
   557        dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
   558      } else {
   559        return;
   560      }
   561  
   562      factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter));
   563      factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter));
   564      factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter));
   565    }
   566  }