e6c0b8c0cf7c1a67d82ea93219c32f8e777b020c
[unical.git] / gson / com / google / gson / GsonBuilder.java
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 java.util.Date}, {@link
372 * java.sql.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 java.text.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 java.text.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 }
This page took 0.037095 seconds and 3 git commands to generate.