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.TreeTypeAdapter;
32 import com.google.gson.internal.bind.TypeAdapters;
33 import com.google.gson.reflect.TypeToken;
34 import com.google.gson.stream.JsonReader;
35
36 import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
37 import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
38 import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
39 import static com.google.gson.Gson.DEFAULT_LENIENT;
40 import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
41 import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
42 import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
43
44 /**
45  * <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
46  * options other than the default. For {@link Gson} with default configuration, it is simpler to
47  * use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
48  * various configuration methods, and finally calling create.</p>
49  *
50  * <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
51  * instance:
52  *
53  * <pre>
54  * Gson gson = new GsonBuilder()
55  *     .registerTypeAdapter(Id.classnew IdTypeAdapter())
56  *     .enableComplexMapKeySerialization()
57  *     .serializeNulls()
58  *     .setDateFormat(DateFormat.LONG)
59  *     .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
60  *     .setPrettyPrinting()
61  *     .setVersion(1.0)
62  *     .create();
63  * </pre></p>
64  *
65  * <p>NOTES:
66  * <ul>
67  * <li> the order of invocation of configuration methods does not matter.</li>
68  * <li> The default serialization of {@link Date} and its subclasses in Gson does
69  *  not contain time-zone information. So, if you are using date/time instances,
70  *  use {@code GsonBuilder} and its {@code setDateFormat} methods.</li>
71  *  </ul>
72  * </p>
73  *
74  * @author Inderjeet Singh
75  * @author Joel Leitch
76  * @author Jesse Wilson
77  */

78 public final class GsonBuilder {
79   private Excluder excluder = Excluder.DEFAULT;
80   private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
81   private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
82   private final Map<Type, InstanceCreator<?>> instanceCreators
83       = new HashMap<Type, InstanceCreator<?>>();
84   private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
85   /** tree-style hierarchy factories. These come after factories for backwards compatibility. */
86   private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>();
87   private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS;
88   private String datePattern;
89   private int dateStyle = DateFormat.DEFAULT;
90   private int timeStyle = DateFormat.DEFAULT;
91   private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS;
92   private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES;
93   private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
94   private boolean prettyPrinting = DEFAULT_PRETTY_PRINT;
95   private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
96   private boolean lenient = DEFAULT_LENIENT;
97
98   /**
99    * Creates a GsonBuilder instance that can be used to build Gson with various configuration
100    * settings. GsonBuilder follows the builder pattern, and it is typically used by first
101    * invoking various configuration methods to set desired options, and finally calling
102    * {@link #create()}.
103    */

104   public GsonBuilder() {
105   }
106
107   /**
108    * Constructs a GsonBuilder instance from a Gson instance. The newly constructed GsonBuilder
109    * has the same configuration as the previously built Gson instance.
110    *
111    * @param gson the gson instance whose configuration should by applied to a new GsonBuilder.
112    */

113   GsonBuilder(Gson gson) {
114     this.excluder = gson.excluder;
115     this.fieldNamingPolicy = gson.fieldNamingStrategy;
116     this.instanceCreators.putAll(gson.instanceCreators);
117     this.serializeNulls = gson.serializeNulls;
118     this.complexMapKeySerialization = gson.complexMapKeySerialization;
119     this.generateNonExecutableJson = gson.generateNonExecutableJson;
120     this.escapeHtmlChars = gson.htmlSafe;
121     this.prettyPrinting = gson.prettyPrinting;
122     this.lenient = gson.lenient;
123     this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
124     this.longSerializationPolicy = gson.longSerializationPolicy;
125     this.datePattern = gson.datePattern;
126     this.dateStyle = gson.dateStyle;
127     this.timeStyle = gson.timeStyle;
128     this.factories.addAll(gson.builderFactories);
129     this.hierarchyFactories.addAll(gson.builderHierarchyFactories);
130   }
131
132   /**
133    * Configures Gson to enable versioning support.
134    *
135    * @param ignoreVersionsAfter any field or type marked with a version higher than this value
136    * are ignored during serialization or deserialization.
137    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
138    */

139   public GsonBuilder setVersion(double ignoreVersionsAfter) {
140     excluder = excluder.withVersion(ignoreVersionsAfter);
141     return this;
142   }
143
144   /**
145    * Configures Gson to excludes all class fields that have the specified modifiers. By default,
146    * Gson will exclude all fields marked transient or static. This method will override that
147    * behavior.
148    *
149    * @param modifiers the field modifiers. You must use the modifiers specified in the
150    * {@link java.lang.reflect.Modifier} class. For example,
151    * {@link java.lang.reflect.Modifier#TRANSIENT},
152    * {@link java.lang.reflect.Modifier#STATIC}.
153    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
154    */

155   public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
156     excluder = excluder.withModifiers(modifiers);
157     return this;
158   }
159
160   /**
161    * Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
162    * special text. This prevents attacks from third-party sites through script sourcing. See
163    * <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
164    * for details.
165    *
166    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
167    * @since 1.3
168    */

169   public GsonBuilder generateNonExecutableJson() {
170     this.generateNonExecutableJson = true;
171     return this;
172   }
173
174   /**
175    * Configures Gson to exclude all fields from consideration for serialization or deserialization
176    * that do not have the {@link com.google.gson.annotations.Expose} annotation.
177    *
178    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
179    */

180   public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
181     excluder = excluder.excludeFieldsWithoutExposeAnnotation();
182     return this;
183   }
184
185   /**
186    * Configure Gson to serialize null fields. By default, Gson omits all fields that are null
187    * during serialization.
188    *
189    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
190    * @since 1.2
191    */

192   public GsonBuilder serializeNulls() {
193     this.serializeNulls = true;
194     return this;
195   }
196
197   /**
198    * Enabling this feature will only change the serialized form if the map key is
199    * a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON
200    * form. The default implementation of map serialization uses {@code toString()}
201    * on the key; however, when this is called then one of the following cases
202    * apply:
203    *
204    * <h3>Maps as JSON objects</h3>
205    * For this case, assume that a type adapter is registered to serialize and
206    * deserialize some {@code Point} class, which contains an x and y coordinate,
207    * to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
208    * then be serialized as a {@link JsonObject}.
209    *
210    * <p>Below is an example:
211    * <pre>  {@code
212    *   Gson gson = new GsonBuilder()
213    *       .register(Point.classnew MyPointTypeAdapter())
214    *       .enableComplexMapKeySerialization()
215    *       .create();
216    *
217    *   Map<Point, String> original = new LinkedHashMap<Point, String>();
218    *   original.put(new Point(5, 6), "a");
219    *   original.put(new Point(8, 8), "b");
220    *   System.out.println(gson.toJson(original, type));
221    * }</pre>
222    * The above code prints this JSON object:<pre>  {@code
223    *   {
224    *     "(5,6)""a",
225    *     "(8,8)""b"
226    *   }
227    * }</pre>
228    *
229    * <h3>Maps as JSON arrays</h3>
230    * For this case, assume that a type adapter was NOT registered for some
231    * {@code Point} class, but rather the default Gson serialization is applied.
232    * In this case, some {@code new Point(2,3)} would serialize as {@code
233    * {"x":2,"y":5}}.
234    *
235    * <p>Given the assumption above, a {@code Map<Point, String>} will be
236    * serialize as an array of arrays (can be viewed as an entry set of pairs).
237    *
238    * <p>Below is an example of serializing complex types as JSON arrays:
239    * <pre> {@code
240    *   Gson gson = new GsonBuilder()
241    *       .enableComplexMapKeySerialization()
242    *       .create();
243    *
244    *   Map<Point, String> original = new LinkedHashMap<Point, String>();
245    *   original.put(new Point(5, 6), "a");
246    *   original.put(new Point(8, 8), "b");
247    *   System.out.println(gson.toJson(original, type));
248    * }
249    *
250    * The JSON output would look as follows:
251    * <pre>   {@code
252    *   [
253    *     [
254    *       {
255    *         "x": 5,
256    *         "y": 6
257    *       },
258    *       "a"
259    *     ],
260    *     [
261    *       {
262    *         "x": 8,
263    *         "y": 8
264    *       },
265    *       "b"
266    *     ]
267    *   ]
268    * }</pre>
269    *
270    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
271    * @since 1.7
272    */

273   public GsonBuilder enableComplexMapKeySerialization() {
274     complexMapKeySerialization = true;
275     return this;
276   }
277
278   /**
279    * Configures Gson to exclude inner classes during serialization.
280    *
281    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
282    * @since 1.3
283    */

284   public GsonBuilder disableInnerClassSerialization() {
285     excluder = excluder.disableInnerClassSerialization();
286     return this;
287   }
288
289   /**
290    * Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
291    * objects.
292    *
293    * @param serializationPolicy the particular policy to use for serializing longs.
294    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
295    * @since 1.3
296    */

297   public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
298     this.longSerializationPolicy = serializationPolicy;
299     return this;
300   }
301
302   /**
303    * Configures Gson to apply a specific naming policy to an object's field during serialization
304    * and deserialization.
305    *
306    * @param namingConvention the JSON field naming convention to use for serialization and
307    * deserialization.
308    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
309    */

310   public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
311     this.fieldNamingPolicy = namingConvention;
312     return this;
313   }
314
315   /**
316    * Configures Gson to apply a specific naming policy strategy to an object's field during
317    * serialization and deserialization.
318    *
319    * @param fieldNamingStrategy the actual naming strategy to apply to the fields
320    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
321    * @since 1.3
322    */

323   public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
324     this.fieldNamingPolicy = fieldNamingStrategy;
325     return this;
326   }
327
328   /**
329    * Configures Gson to apply a set of exclusion strategies during both serialization and
330    * deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
331    * This means that if one of the {@code strategies} suggests that a field (or class) should be
332    * skipped then that field (or object) is skipped during serialization/deserialization.
333    *
334    * @param strategies the set of strategy object to apply during object (de)serialization.
335    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
336    * @since 1.4
337    */

338   public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
339     for (ExclusionStrategy strategy : strategies) {
340       excluder = excluder.withExclusionStrategy(strategy, truetrue);
341     }
342     return this;
343   }
344
345   /**
346    * Configures Gson to apply the passed in exclusion strategy during serialization.
347    * If this method is invoked numerous times with different exclusion strategy objects
348    * then the exclusion strategies that were added will be applied as a disjunction rule.
349    * This means that if one of the added exclusion strategies suggests that a field (or
350    * class) should be skipped then that field (or object) is skipped during its
351    * serialization.
352    *
353    * @param strategy an exclusion strategy to apply during serialization.
354    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
355    * @since 1.7
356    */

357   public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
358     excluder = excluder.withExclusionStrategy(strategy, truefalse);
359     return this;
360   }
361
362   /**
363    * Configures Gson to apply the passed in exclusion strategy during deserialization.
364    * If this method is invoked numerous times with different exclusion strategy objects
365    * then the exclusion strategies that were added will be applied as a disjunction rule.
366    * This means that if one of the added exclusion strategies suggests that a field (or
367    * class) should be skipped then that field (or object) is skipped during its
368    * deserialization.
369    *
370    * @param strategy an exclusion strategy to apply during deserialization.
371    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
372    * @since 1.7
373    */

374   public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
375     excluder = excluder.withExclusionStrategy(strategy, falsetrue);
376     return this;
377   }
378
379   /**
380    * Configures Gson to output Json that fits in a page for pretty printing. This option only
381    * affects Json serialization.
382    *
383    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
384    */

385   public GsonBuilder setPrettyPrinting() {
386     prettyPrinting = true;
387     return this;
388   }
389
390   /**
391    * By default, Gson is strict and only accepts JSON as specified by
392    * <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. This option makes the parser
393    * liberal in what it accepts.
394    *
395    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
396    * @see JsonReader#setLenient(boolean)
397    */

398   public GsonBuilder setLenient() {
399     lenient = true;
400     return this;
401   }
402
403   /**
404    * By default, Gson escapes HTML characters such as &lt; &gt; etc. Use this option to configure
405    * Gson to pass-through HTML characters as is.
406    *
407    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
408    * @since 1.3
409    */

410   public GsonBuilder disableHtmlEscaping() {
411     this.escapeHtmlChars = false;
412     return this;
413   }
414
415   /**
416    * Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
417    * call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
418    * will be used to decide the serialization format.
419    *
420    * <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
421    * java.sql.Timestamp} and {@link java.sql.Date}.
422    *
423    * <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
424    * class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
425    * valid date and time patterns.</p>
426    *
427    * @param pattern the pattern that dates will be serialized/deserialized to/from
428    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
429    * @since 1.2
430    */

431   public GsonBuilder setDateFormat(String pattern) {
432     // TODO(Joel): Make this fail fast if it is an invalid date format
433     this.datePattern = pattern;
434     return this;
435   }
436
437   /**
438    * Configures Gson to to serialize {@code Date} objects according to the style value provided.
439    * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
440    * invocation will be used to decide the serialization format.
441    *
442    * <p>Note that this style value should be one of the predefined constants in the
443    * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
444    * information on the valid style constants.</p>
445    *
446    * @param style the predefined date style that date objects will be serialized/deserialized
447    * to/from
448    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
449    * @since 1.2
450    */

451   public GsonBuilder setDateFormat(int style) {
452     this.dateStyle = style;
453     this.datePattern = null;
454     return this;
455   }
456
457   /**
458    * Configures Gson to to serialize {@code Date} objects according to the style value provided.
459    * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
460    * invocation will be used to decide the serialization format.
461    *
462    * <p>Note that this style value should be one of the predefined constants in the
463    * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
464    * information on the valid style constants.</p>
465    *
466    * @param dateStyle the predefined date style that date objects will be serialized/deserialized
467    * to/from
468    * @param timeStyle the predefined style for the time portion of the date objects
469    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
470    * @since 1.2
471    */

472   public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
473     this.dateStyle = dateStyle;
474     this.timeStyle = timeStyle;
475     this.datePattern = null;
476     return this;
477   }
478
479   /**
480    * Configures Gson for custom serialization or deserialization. This method combines the
481    * registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a
482    * {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
483    * all the required interfaces for custom serialization with Gson. If a type adapter was
484    * previously registered for the specified {@code type}, it is overwritten.
485    *
486    * <p>This registers the type specified and no other types: you must manually register related
487    * types! For example, applications registering {@code boolean.class} should also register {@code
488    * Boolean.class}.
489    *
490    * @param type the type definition for the type adapter being registered
491    * @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
492    * {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
493    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
494    */

495   @SuppressWarnings({"unchecked""rawtypes"})
496   public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
497     $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
498         || typeAdapter instanceof JsonDeserializer<?>
499         || typeAdapter instanceof InstanceCreator<?>
500         || typeAdapter instanceof TypeAdapter<?>);
501     if (typeAdapter instanceof InstanceCreator<?>) {
502       instanceCreators.put(type, (InstanceCreator) typeAdapter);
503     }
504     if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
505       TypeToken<?> typeToken = TypeToken.get(type);
506       factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
507     }
508     if (typeAdapter instanceof TypeAdapter<?>) {
509       factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
510     }
511     return this;
512   }
513
514   /**
515    * Register a factory for type adapters. Registering a factory is useful when the type
516    * adapter needs to be configured based on the type of the field being processed. Gson
517    * is designed to handle a large number of factories, so you should consider registering
518    * them to be at par with registering an individual type adapter.
519    *
520    * @since 2.1
521    */

522   public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
523     factories.add(factory);
524     return this;
525   }
526
527   /**
528    * Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
529    * This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and
530    * a {@link JsonDeserializer}. If a type adapter was previously registered for the specified
531    * type hierarchy, it is overridden. If a type adapter is registered for a specific type in
532    * the type hierarchy, it will be invoked instead of the one registered for the type hierarchy.
533    *
534    * @param baseType the class definition for the type adapter being registered for the base class
535    *        or interface
536    * @param typeAdapter This object must implement at least one of {@link TypeAdapter},
537    *        {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
538    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
539    * @since 1.7
540    */

541   @SuppressWarnings({"unchecked""rawtypes"})
542   public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
543     $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
544         || typeAdapter instanceof JsonDeserializer<?>
545         || typeAdapter instanceof TypeAdapter<?>);
546     if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
547       hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
548     }
549     if (typeAdapter instanceof TypeAdapter<?>) {
550       factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
551     }
552     return this;
553   }
554
555   /**
556    * Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
557    * special double values (NaN, Infinity, -Infinity). However,
558    * <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
559    * specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
560    * values. Moreover, most JavaScript engines will accept these special values in JSON without
561    * problem. So, at a practical level, it makes sense to accept these values as valid JSON even
562    * though JSON specification disallows them.
563    *
564    * <p>Gson always accepts these special values during deserialization. However, it outputs
565    * strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
566    * {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
567    * {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
568    * will throw an {@link IllegalArgumentException}. This method provides a way to override the
569    * default behavior when you know that the JSON receiver will be able to handle these special
570    * values.
571    *
572    * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
573    * @since 1.3
574    */

575   public GsonBuilder serializeSpecialFloatingPointValues() {
576     this.serializeSpecialFloatingPointValues = true;
577     return this;
578   }
579
580   /**
581    * Creates a {@link Gson} instance based on the current configuration. This method is free of
582    * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
583    *
584    * @return an instance of Gson configured with the options currently set in this builder
585    */

586   public Gson create() {
587     List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(this.factories.size() + this.hierarchyFactories.size() + 3);
588     factories.addAll(this.factories);
589     Collections.reverse(factories);
590
591     List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>(this.hierarchyFactories);
592     Collections.reverse(hierarchyFactories);
593     factories.addAll(hierarchyFactories);
594
595     addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
596
597     return new Gson(excluder, fieldNamingPolicy, instanceCreators,
598         serializeNulls, complexMapKeySerialization,
599         generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
600         serializeSpecialFloatingPointValues, longSerializationPolicy,
601         datePattern, dateStyle, timeStyle,
602         this.factories, this.hierarchyFactories, factories);
603   }
604
605   @SuppressWarnings("unchecked")
606   private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
607       List<TypeAdapterFactory> factories) {
608     DefaultDateTypeAdapter dateTypeAdapter;
609     TypeAdapter<Timestamp> timestampTypeAdapter;
610     TypeAdapter<java.sql.Date> javaSqlDateTypeAdapter;
611     if (datePattern != null && !"".equals(datePattern.trim())) {
612       dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, datePattern);
613       timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, datePattern);
614       javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, datePattern);
615     } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
616       dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, dateStyle, timeStyle);
617       timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, dateStyle, timeStyle);
618       javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, dateStyle, timeStyle);
619     } else {
620       return;
621     }
622
623     factories.add(TypeAdapters.newFactory(Date.class, dateTypeAdapter));
624     factories.add(TypeAdapters.newFactory(Timestamp.class, timestampTypeAdapter));
625     factories.add(TypeAdapters.newFactory(java.sql.Date.class, javaSqlDateTypeAdapter));
626   }
627 }
628