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