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