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 < > 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 }