xref: /aosp_15_r20/external/gson/UserGuide.md (revision a8de600362638ea28fd6cb3225451dc706d269bb)
1*a8de6003SAndroid Build Coastguard Worker# Gson User Guide
2*a8de6003SAndroid Build Coastguard Worker
3*a8de6003SAndroid Build Coastguard Worker1. [Overview](#overview)
4*a8de6003SAndroid Build Coastguard Worker2. [Goals for Gson](#goals-for-gson)
5*a8de6003SAndroid Build Coastguard Worker3. [Gson Performance and Scalability](#gson-performance-and-scalability)
6*a8de6003SAndroid Build Coastguard Worker4. [Gson Users](#gson-users)
7*a8de6003SAndroid Build Coastguard Worker5. [Using Gson](#using-gson)
8*a8de6003SAndroid Build Coastguard Worker   * [Using Gson with Gradle/Android](#using-gson-with-gradleandroid)
9*a8de6003SAndroid Build Coastguard Worker   * [Using Gson with Maven](#using-gson-with-maven)
10*a8de6003SAndroid Build Coastguard Worker   * [Primitives Examples](#primitives-examples)
11*a8de6003SAndroid Build Coastguard Worker   * [Object Examples](#object-examples)
12*a8de6003SAndroid Build Coastguard Worker   * [Finer Points with Objects](#finer-points-with-objects)
13*a8de6003SAndroid Build Coastguard Worker   * [Nested Classes (including Inner Classes)](#nested-classes-including-inner-classes)
14*a8de6003SAndroid Build Coastguard Worker   * [Array Examples](#array-examples)
15*a8de6003SAndroid Build Coastguard Worker   * [Collections Examples](#collections-examples)
16*a8de6003SAndroid Build Coastguard Worker     * [Collections Limitations](#collections-limitations)
17*a8de6003SAndroid Build Coastguard Worker   * [Maps Examples](#maps-examples)
18*a8de6003SAndroid Build Coastguard Worker   * [Serializing and Deserializing Generic Types](#serializing-and-deserializing-generic-types)
19*a8de6003SAndroid Build Coastguard Worker   * [Serializing and Deserializing Collection with Objects of Arbitrary Types](#serializing-and-deserializing-collection-with-objects-of-arbitrary-types)
20*a8de6003SAndroid Build Coastguard Worker   * [Built-in Serializers and Deserializers](#built-in-serializers-and-deserializers)
21*a8de6003SAndroid Build Coastguard Worker   * [Custom Serialization and Deserialization](#custom-serialization-and-deserialization)
22*a8de6003SAndroid Build Coastguard Worker     * [Writing a Serializer](#writing-a-serializer)
23*a8de6003SAndroid Build Coastguard Worker     * [Writing a Deserializer](#writing-a-deserializer)
24*a8de6003SAndroid Build Coastguard Worker   * [Writing an Instance Creator](#writing-an-instance-creator)
25*a8de6003SAndroid Build Coastguard Worker     * [InstanceCreator for a Parameterized Type](#instancecreator-for-a-parameterized-type)
26*a8de6003SAndroid Build Coastguard Worker   * [Compact Vs. Pretty Printing for JSON Output Format](#compact-vs-pretty-printing-for-json-output-format)
27*a8de6003SAndroid Build Coastguard Worker   * [Null Object Support](#null-object-support)
28*a8de6003SAndroid Build Coastguard Worker   * [Versioning Support](#versioning-support)
29*a8de6003SAndroid Build Coastguard Worker   * [Excluding Fields From Serialization and Deserialization](#excluding-fields-from-serialization-and-deserialization)
30*a8de6003SAndroid Build Coastguard Worker     * [Java Modifier Exclusion](#java-modifier-exclusion)
31*a8de6003SAndroid Build Coastguard Worker     * [Gson's `@Expose`](#gsons-expose)
32*a8de6003SAndroid Build Coastguard Worker     * [User Defined Exclusion Strategies](#user-defined-exclusion-strategies)
33*a8de6003SAndroid Build Coastguard Worker   * [JSON Field Naming Support](#json-field-naming-support)
34*a8de6003SAndroid Build Coastguard Worker   * [Sharing State Across Custom Serializers and Deserializers](#sharing-state-across-custom-serializers-and-deserializers)
35*a8de6003SAndroid Build Coastguard Worker   * [Streaming](#streaming)
36*a8de6003SAndroid Build Coastguard Worker6. [Issues in Designing Gson](#issues-in-designing-gson)
37*a8de6003SAndroid Build Coastguard Worker7. [Future Enhancements to Gson](#future-enhancements-to-gson)
38*a8de6003SAndroid Build Coastguard Worker
39*a8de6003SAndroid Build Coastguard Worker## Overview
40*a8de6003SAndroid Build Coastguard Worker
41*a8de6003SAndroid Build Coastguard WorkerGson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object.
42*a8de6003SAndroid Build Coastguard Worker
43*a8de6003SAndroid Build Coastguard WorkerGson can work with arbitrary Java objects including pre-existing objects that you do not have source code of.
44*a8de6003SAndroid Build Coastguard Worker
45*a8de6003SAndroid Build Coastguard Worker## Goals for Gson
46*a8de6003SAndroid Build Coastguard Worker
47*a8de6003SAndroid Build Coastguard Worker* Provide easy to use mechanisms like `toString()` and constructor (factory method) to convert Java to JSON and vice-versa
48*a8de6003SAndroid Build Coastguard Worker* Allow pre-existing unmodifiable objects to be converted to and from JSON
49*a8de6003SAndroid Build Coastguard Worker* Allow custom representations for objects
50*a8de6003SAndroid Build Coastguard Worker* Support arbitrarily complex objects
51*a8de6003SAndroid Build Coastguard Worker* Generate compact and readable JSON output
52*a8de6003SAndroid Build Coastguard Worker
53*a8de6003SAndroid Build Coastguard Worker## Gson Performance and Scalability
54*a8de6003SAndroid Build Coastguard Worker
55*a8de6003SAndroid Build Coastguard WorkerHere are some metrics that we obtained on a desktop (dual opteron, 8GB RAM, 64-bit Ubuntu) running lots of other things along-with the tests. You can rerun these tests by using the class [`PerformanceTest`](gson/src/test/java/com/google/gson/metrics/PerformanceTest.java).
56*a8de6003SAndroid Build Coastguard Worker
57*a8de6003SAndroid Build Coastguard Worker* Strings: Deserialized strings of over 25MB without any problems (see `disabled_testStringDeserializationPerformance` method in `PerformanceTest`)
58*a8de6003SAndroid Build Coastguard Worker* Large collections:
59*a8de6003SAndroid Build Coastguard Worker  * Serialized a collection of 1.4 million objects (see `disabled_testLargeCollectionSerialization` method in `PerformanceTest`)
60*a8de6003SAndroid Build Coastguard Worker  * Deserialized a collection of 87,000 objects (see `disabled_testLargeCollectionDeserialization` in `PerformanceTest`)
61*a8de6003SAndroid Build Coastguard Worker* Gson 1.4 raised the deserialization limit for byte arrays and collection to over 11MB from 80KB.
62*a8de6003SAndroid Build Coastguard Worker
63*a8de6003SAndroid Build Coastguard WorkerNote: Delete the `disabled_` prefix to run these tests. We use this prefix to prevent running these tests every time we run JUnit tests.
64*a8de6003SAndroid Build Coastguard Worker
65*a8de6003SAndroid Build Coastguard Worker## Gson Users
66*a8de6003SAndroid Build Coastguard Worker
67*a8de6003SAndroid Build Coastguard WorkerGson was originally created for use inside Google where it is currently used in a number of projects. It is now used by a number of public projects and companies.
68*a8de6003SAndroid Build Coastguard Worker
69*a8de6003SAndroid Build Coastguard Worker## Using Gson
70*a8de6003SAndroid Build Coastguard Worker
71*a8de6003SAndroid Build Coastguard WorkerThe primary class to use is [`Gson`](gson/src/main/java/com/google/gson/Gson.java) which you can just create by calling `new Gson()`. There is also a class [`GsonBuilder`](gson/src/main/java/com/google/gson/GsonBuilder.java) available that can be used to create a Gson instance with various settings like version control and so on.
72*a8de6003SAndroid Build Coastguard Worker
73*a8de6003SAndroid Build Coastguard WorkerThe Gson instance does not maintain any state while invoking JSON operations. So, you are free to reuse the same object for multiple JSON serialization and deserialization operations.
74*a8de6003SAndroid Build Coastguard Worker
75*a8de6003SAndroid Build Coastguard Worker## Using Gson with Gradle/Android
76*a8de6003SAndroid Build Coastguard Worker
77*a8de6003SAndroid Build Coastguard Worker```gradle
78*a8de6003SAndroid Build Coastguard Workerdependencies {
79*a8de6003SAndroid Build Coastguard Worker    implementation 'com.google.code.gson:gson:2.10.1'
80*a8de6003SAndroid Build Coastguard Worker}
81*a8de6003SAndroid Build Coastguard Worker```
82*a8de6003SAndroid Build Coastguard Worker
83*a8de6003SAndroid Build Coastguard Worker## Using Gson with Maven
84*a8de6003SAndroid Build Coastguard Worker
85*a8de6003SAndroid Build Coastguard WorkerTo use Gson with Maven2/3, you can use the Gson version available in Maven Central by adding the following dependency:
86*a8de6003SAndroid Build Coastguard Worker
87*a8de6003SAndroid Build Coastguard Worker```xml
88*a8de6003SAndroid Build Coastguard Worker<dependencies>
89*a8de6003SAndroid Build Coastguard Worker    <!--  Gson: Java to JSON conversion -->
90*a8de6003SAndroid Build Coastguard Worker    <dependency>
91*a8de6003SAndroid Build Coastguard Worker      <groupId>com.google.code.gson</groupId>
92*a8de6003SAndroid Build Coastguard Worker      <artifactId>gson</artifactId>
93*a8de6003SAndroid Build Coastguard Worker      <version>2.10.1</version>
94*a8de6003SAndroid Build Coastguard Worker      <scope>compile</scope>
95*a8de6003SAndroid Build Coastguard Worker    </dependency>
96*a8de6003SAndroid Build Coastguard Worker</dependencies>
97*a8de6003SAndroid Build Coastguard Worker```
98*a8de6003SAndroid Build Coastguard Worker
99*a8de6003SAndroid Build Coastguard WorkerThat is it, now your Maven project is Gson enabled.
100*a8de6003SAndroid Build Coastguard Worker
101*a8de6003SAndroid Build Coastguard Worker### Primitives Examples
102*a8de6003SAndroid Build Coastguard Worker
103*a8de6003SAndroid Build Coastguard Worker```java
104*a8de6003SAndroid Build Coastguard Worker// Serialization
105*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
106*a8de6003SAndroid Build Coastguard Workergson.toJson(1);            // ==> 1
107*a8de6003SAndroid Build Coastguard Workergson.toJson("abcd");       // ==> "abcd"
108*a8de6003SAndroid Build Coastguard Workergson.toJson(new Long(10)); // ==> 10
109*a8de6003SAndroid Build Coastguard Workerint[] values = { 1 };
110*a8de6003SAndroid Build Coastguard Workergson.toJson(values);       // ==> [1]
111*a8de6003SAndroid Build Coastguard Worker
112*a8de6003SAndroid Build Coastguard Worker// Deserialization
113*a8de6003SAndroid Build Coastguard Workerint i = gson.fromJson("1", int.class);
114*a8de6003SAndroid Build Coastguard WorkerInteger intObj = gson.fromJson("1", Integer.class);
115*a8de6003SAndroid Build Coastguard WorkerLong longObj = gson.fromJson("1", Long.class);
116*a8de6003SAndroid Build Coastguard WorkerBoolean boolObj = gson.fromJson("false", Boolean.class);
117*a8de6003SAndroid Build Coastguard WorkerString str = gson.fromJson("\"abc\"", String.class);
118*a8de6003SAndroid Build Coastguard WorkerString[] strArray = gson.fromJson("[\"abc\"]", String[].class);
119*a8de6003SAndroid Build Coastguard Worker```
120*a8de6003SAndroid Build Coastguard Worker
121*a8de6003SAndroid Build Coastguard Worker### Object Examples
122*a8de6003SAndroid Build Coastguard Worker
123*a8de6003SAndroid Build Coastguard Worker```java
124*a8de6003SAndroid Build Coastguard Workerclass BagOfPrimitives {
125*a8de6003SAndroid Build Coastguard Worker  private int value1 = 1;
126*a8de6003SAndroid Build Coastguard Worker  private String value2 = "abc";
127*a8de6003SAndroid Build Coastguard Worker  private transient int value3 = 3;
128*a8de6003SAndroid Build Coastguard Worker  BagOfPrimitives() {
129*a8de6003SAndroid Build Coastguard Worker    // no-args constructor
130*a8de6003SAndroid Build Coastguard Worker  }
131*a8de6003SAndroid Build Coastguard Worker}
132*a8de6003SAndroid Build Coastguard Worker
133*a8de6003SAndroid Build Coastguard Worker// Serialization
134*a8de6003SAndroid Build Coastguard WorkerBagOfPrimitives obj = new BagOfPrimitives();
135*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
136*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(obj);
137*a8de6003SAndroid Build Coastguard Worker
138*a8de6003SAndroid Build Coastguard Worker// ==> json is {"value1":1,"value2":"abc"}
139*a8de6003SAndroid Build Coastguard Worker```
140*a8de6003SAndroid Build Coastguard Worker
141*a8de6003SAndroid Build Coastguard WorkerNote that you can not serialize objects with circular references since that will result in infinite recursion.
142*a8de6003SAndroid Build Coastguard Worker
143*a8de6003SAndroid Build Coastguard Worker```java
144*a8de6003SAndroid Build Coastguard Worker// Deserialization
145*a8de6003SAndroid Build Coastguard WorkerBagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
146*a8de6003SAndroid Build Coastguard Worker// ==> obj2 is just like obj
147*a8de6003SAndroid Build Coastguard Worker```
148*a8de6003SAndroid Build Coastguard Worker
149*a8de6003SAndroid Build Coastguard Worker#### **Finer Points with Objects**
150*a8de6003SAndroid Build Coastguard Worker
151*a8de6003SAndroid Build Coastguard Worker* It is perfectly fine (and recommended) to use private fields.
152*a8de6003SAndroid Build Coastguard Worker* There is no need to use any annotations to indicate a field is to be included for serialization and deserialization. All fields in the current class (and from all super classes) are included by default.
153*a8de6003SAndroid Build Coastguard Worker* If a field is marked transient, (by default) it is ignored and not included in the JSON serialization or deserialization.
154*a8de6003SAndroid Build Coastguard Worker* This implementation handles nulls correctly.
155*a8de6003SAndroid Build Coastguard Worker  * While serializing, a null field is omitted from the output.
156*a8de6003SAndroid Build Coastguard Worker  * While deserializing, a missing entry in JSON results in setting the corresponding field in the object to its default value: null for object types, zero for numeric types, and false for booleans.
157*a8de6003SAndroid Build Coastguard Worker* If a field is _synthetic_, it is ignored and not included in JSON serialization or deserialization.
158*a8de6003SAndroid Build Coastguard Worker* Fields corresponding to the outer classes in inner classes are ignored and not included in serialization or deserialization.
159*a8de6003SAndroid Build Coastguard Worker* Anonymous and local classes are excluded. They will be serialized as JSON `null` and when deserialized their JSON value is ignored and `null` is returned. Convert the classes to `static` nested classes to enable serialization and deserialization for them.
160*a8de6003SAndroid Build Coastguard Worker
161*a8de6003SAndroid Build Coastguard Worker### Nested Classes (including Inner Classes)
162*a8de6003SAndroid Build Coastguard Worker
163*a8de6003SAndroid Build Coastguard WorkerGson can serialize static nested classes quite easily.
164*a8de6003SAndroid Build Coastguard Worker
165*a8de6003SAndroid Build Coastguard WorkerGson can also deserialize static nested classes. However, Gson can **not** automatically deserialize the **pure inner classes since their no-args constructor also need a reference to the containing Object** which is not available at the time of deserialization. You can address this problem by either making the inner class static or by providing a custom InstanceCreator for it. Here is an example:
166*a8de6003SAndroid Build Coastguard Worker
167*a8de6003SAndroid Build Coastguard Worker```java
168*a8de6003SAndroid Build Coastguard Workerpublic class A {
169*a8de6003SAndroid Build Coastguard Worker  public String a;
170*a8de6003SAndroid Build Coastguard Worker
171*a8de6003SAndroid Build Coastguard Worker  class B {
172*a8de6003SAndroid Build Coastguard Worker
173*a8de6003SAndroid Build Coastguard Worker    public String b;
174*a8de6003SAndroid Build Coastguard Worker
175*a8de6003SAndroid Build Coastguard Worker    public B() {
176*a8de6003SAndroid Build Coastguard Worker      // No args constructor for B
177*a8de6003SAndroid Build Coastguard Worker    }
178*a8de6003SAndroid Build Coastguard Worker  }
179*a8de6003SAndroid Build Coastguard Worker}
180*a8de6003SAndroid Build Coastguard Worker```
181*a8de6003SAndroid Build Coastguard Worker
182*a8de6003SAndroid Build Coastguard Worker**NOTE**: The above class B can not (by default) be serialized with Gson.
183*a8de6003SAndroid Build Coastguard Worker
184*a8de6003SAndroid Build Coastguard WorkerGson can not deserialize `{"b":"abc"}` into an instance of B since the class B is an inner class. If it was defined as static class B then Gson would have been able to deserialize the string. Another solution is to write a custom instance creator for B.
185*a8de6003SAndroid Build Coastguard Worker
186*a8de6003SAndroid Build Coastguard Worker```java
187*a8de6003SAndroid Build Coastguard Workerpublic class InstanceCreatorForB implements InstanceCreator<A.B> {
188*a8de6003SAndroid Build Coastguard Worker  private final A a;
189*a8de6003SAndroid Build Coastguard Worker  public InstanceCreatorForB(A a)  {
190*a8de6003SAndroid Build Coastguard Worker    this.a = a;
191*a8de6003SAndroid Build Coastguard Worker  }
192*a8de6003SAndroid Build Coastguard Worker  public A.B createInstance(Type type) {
193*a8de6003SAndroid Build Coastguard Worker    return a.new B();
194*a8de6003SAndroid Build Coastguard Worker  }
195*a8de6003SAndroid Build Coastguard Worker}
196*a8de6003SAndroid Build Coastguard Worker```
197*a8de6003SAndroid Build Coastguard Worker
198*a8de6003SAndroid Build Coastguard WorkerThe above is possible, but not recommended.
199*a8de6003SAndroid Build Coastguard Worker
200*a8de6003SAndroid Build Coastguard Worker### Array Examples
201*a8de6003SAndroid Build Coastguard Worker
202*a8de6003SAndroid Build Coastguard Worker```java
203*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
204*a8de6003SAndroid Build Coastguard Workerint[] ints = {1, 2, 3, 4, 5};
205*a8de6003SAndroid Build Coastguard WorkerString[] strings = {"abc", "def", "ghi"};
206*a8de6003SAndroid Build Coastguard Worker
207*a8de6003SAndroid Build Coastguard Worker// Serialization
208*a8de6003SAndroid Build Coastguard Workergson.toJson(ints);     // ==> [1,2,3,4,5]
209*a8de6003SAndroid Build Coastguard Workergson.toJson(strings);  // ==> ["abc", "def", "ghi"]
210*a8de6003SAndroid Build Coastguard Worker
211*a8de6003SAndroid Build Coastguard Worker// Deserialization
212*a8de6003SAndroid Build Coastguard Workerint[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
213*a8de6003SAndroid Build Coastguard Worker// ==> ints2 will be same as ints
214*a8de6003SAndroid Build Coastguard Worker```
215*a8de6003SAndroid Build Coastguard Worker
216*a8de6003SAndroid Build Coastguard WorkerWe also support multi-dimensional arrays, with arbitrarily complex element types.
217*a8de6003SAndroid Build Coastguard Worker
218*a8de6003SAndroid Build Coastguard Worker### Collections Examples
219*a8de6003SAndroid Build Coastguard Worker
220*a8de6003SAndroid Build Coastguard Worker```java
221*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
222*a8de6003SAndroid Build Coastguard WorkerCollection<Integer> ints = Arrays.asList(1,2,3,4,5);
223*a8de6003SAndroid Build Coastguard Worker
224*a8de6003SAndroid Build Coastguard Worker// Serialization
225*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]
226*a8de6003SAndroid Build Coastguard Worker
227*a8de6003SAndroid Build Coastguard Worker// Deserialization
228*a8de6003SAndroid Build Coastguard WorkerTypeToken<Collection<Integer>> collectionType = new TypeToken<Collection<Integer>>(){};
229*a8de6003SAndroid Build Coastguard Worker// Note: For older Gson versions it is necessary to use `collectionType.getType()` as argument below,
230*a8de6003SAndroid Build Coastguard Worker// this is however not type-safe and care must be taken to specify the correct type for the local variable
231*a8de6003SAndroid Build Coastguard WorkerCollection<Integer> ints2 = gson.fromJson(json, collectionType);
232*a8de6003SAndroid Build Coastguard Worker// ==> ints2 is same as ints
233*a8de6003SAndroid Build Coastguard Worker```
234*a8de6003SAndroid Build Coastguard Worker
235*a8de6003SAndroid Build Coastguard WorkerFairly hideous: note how we define the type of collection.
236*a8de6003SAndroid Build Coastguard WorkerUnfortunately, there is no way to get around this in Java.
237*a8de6003SAndroid Build Coastguard Worker
238*a8de6003SAndroid Build Coastguard Worker#### Collections Limitations
239*a8de6003SAndroid Build Coastguard Worker
240*a8de6003SAndroid Build Coastguard WorkerGson can serialize collection of arbitrary objects but can not deserialize from it, because there is no way for the user to indicate the type of the resulting object. Instead, while deserializing, the Collection must be of a specific, generic type.
241*a8de6003SAndroid Build Coastguard WorkerThis makes sense, and is rarely a problem when following good Java coding practices.
242*a8de6003SAndroid Build Coastguard Worker
243*a8de6003SAndroid Build Coastguard Worker### Maps Examples
244*a8de6003SAndroid Build Coastguard Worker
245*a8de6003SAndroid Build Coastguard WorkerGson by default serializes any `java.util.Map` implementation as a JSON object. Because JSON objects only support strings as member names, Gson converts the Map keys to strings by calling `toString()` on them, and using `"null"` for `null` keys:
246*a8de6003SAndroid Build Coastguard Worker
247*a8de6003SAndroid Build Coastguard Worker```java
248*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
249*a8de6003SAndroid Build Coastguard WorkerMap<String, String> stringMap = new LinkedHashMap<>();
250*a8de6003SAndroid Build Coastguard WorkerstringMap.put("key", "value");
251*a8de6003SAndroid Build Coastguard WorkerstringMap.put(null, "null-entry");
252*a8de6003SAndroid Build Coastguard Worker
253*a8de6003SAndroid Build Coastguard Worker// Serialization
254*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(stringMap); // ==> json is {"key":"value","null":"null-entry"}
255*a8de6003SAndroid Build Coastguard Worker
256*a8de6003SAndroid Build Coastguard WorkerMap<Integer, Integer> intMap = new LinkedHashMap<>();
257*a8de6003SAndroid Build Coastguard WorkerintMap.put(2, 4);
258*a8de6003SAndroid Build Coastguard WorkerintMap.put(3, 6);
259*a8de6003SAndroid Build Coastguard Worker
260*a8de6003SAndroid Build Coastguard Worker// Serialization
261*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(intMap); // ==> json is {"2":4,"3":6}
262*a8de6003SAndroid Build Coastguard Worker```
263*a8de6003SAndroid Build Coastguard Worker
264*a8de6003SAndroid Build Coastguard WorkerFor deserialization Gson uses the `read` method of the `TypeAdapter` registered for the Map key type. Similar to the Collection example shown above, for deserialization a `TypeToken` has to be used to tell Gson what types the Map keys and values have:
265*a8de6003SAndroid Build Coastguard Worker
266*a8de6003SAndroid Build Coastguard Worker```java
267*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
268*a8de6003SAndroid Build Coastguard WorkerTypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
269*a8de6003SAndroid Build Coastguard WorkerString json = "{\"key\": \"value\"}";
270*a8de6003SAndroid Build Coastguard Worker
271*a8de6003SAndroid Build Coastguard Worker// Deserialization
272*a8de6003SAndroid Build Coastguard Worker// Note: For older Gson versions it is necessary to use `mapType.getType()` as argument below,
273*a8de6003SAndroid Build Coastguard Worker// this is however not type-safe and care must be taken to specify the correct type for the local variable
274*a8de6003SAndroid Build Coastguard WorkerMap<String, String> stringMap = gson.fromJson(json, mapType);
275*a8de6003SAndroid Build Coastguard Worker// ==> stringMap is {key=value}
276*a8de6003SAndroid Build Coastguard Worker```
277*a8de6003SAndroid Build Coastguard Worker
278*a8de6003SAndroid Build Coastguard WorkerGson also supports using complex types as Map keys. This feature can be enabled with [`GsonBuilder.enableComplexMapKeySerialization()`](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/GsonBuilder.html#enableComplexMapKeySerialization()). If enabled, Gson uses the `write` method of the `TypeAdapter` registered for the Map key type to serialize the keys, instead of using `toString()`. When any of the keys is serialized by the adapter as JSON array or JSON object, Gson will serialize the complete Map as JSON array, consisting of key-value pairs (encoded as JSON array). Otherwise, if none of the keys is serialized as a JSON array or JSON object, Gson will use a JSON object to encode the Map:
279*a8de6003SAndroid Build Coastguard Worker
280*a8de6003SAndroid Build Coastguard Worker```java
281*a8de6003SAndroid Build Coastguard Workerclass PersonName {
282*a8de6003SAndroid Build Coastguard Worker  String firstName;
283*a8de6003SAndroid Build Coastguard Worker  String lastName;
284*a8de6003SAndroid Build Coastguard Worker
285*a8de6003SAndroid Build Coastguard Worker  PersonName(String firstName, String lastName) {
286*a8de6003SAndroid Build Coastguard Worker    this.firstName = firstName;
287*a8de6003SAndroid Build Coastguard Worker    this.lastName = lastName;
288*a8de6003SAndroid Build Coastguard Worker  }
289*a8de6003SAndroid Build Coastguard Worker
290*a8de6003SAndroid Build Coastguard Worker  // ... equals and hashCode
291*a8de6003SAndroid Build Coastguard Worker}
292*a8de6003SAndroid Build Coastguard Worker
293*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
294*a8de6003SAndroid Build Coastguard WorkerMap<PersonName, Integer> complexMap = new LinkedHashMap<>();
295*a8de6003SAndroid Build Coastguard WorkercomplexMap.put(new PersonName("John", "Doe"), 30);
296*a8de6003SAndroid Build Coastguard WorkercomplexMap.put(new PersonName("Jane", "Doe"), 35);
297*a8de6003SAndroid Build Coastguard Worker
298*a8de6003SAndroid Build Coastguard Worker// Serialization; complex map is serialized as a JSON array containing key-value pairs (as JSON arrays)
299*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(complexMap);
300*a8de6003SAndroid Build Coastguard Worker// ==> json is [[{"firstName":"John","lastName":"Doe"},30],[{"firstName":"Jane","lastName":"Doe"},35]]
301*a8de6003SAndroid Build Coastguard Worker
302*a8de6003SAndroid Build Coastguard WorkerMap<String, String> stringMap = new LinkedHashMap<>();
303*a8de6003SAndroid Build Coastguard WorkerstringMap.put("key", "value");
304*a8de6003SAndroid Build Coastguard Worker// Serialization; non-complex map is serialized as a regular JSON object
305*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(stringMap); // json is {"key":"value"}
306*a8de6003SAndroid Build Coastguard Worker```
307*a8de6003SAndroid Build Coastguard Worker
308*a8de6003SAndroid Build Coastguard Worker**Important:** Because Gson by default uses `toString()` to serialize Map keys, this can lead to malformed encoded keys or can cause mismatch between serialization and deserialization of the keys, for example when `toString()` is not properly implemented. A workaround for this can be to use `enableComplexMapKeySerialization()` to make sure the `TypeAdapter` registered for the Map key type is used for deserialization _and_ serialization. As shown in the example above, when none of the keys are serialized by the adapter as JSON array or JSON object, the Map is serialized as a regular JSON object, as desired.
309*a8de6003SAndroid Build Coastguard Worker
310*a8de6003SAndroid Build Coastguard WorkerNote that when deserializing enums as Map keys, if Gson is unable to find an enum constant with a matching `name()` value respectively `@SerializedName` annotation, it falls back to looking up the enum constant by its `toString()` value. This is to work around the issue described above, but only applies to enum constants.
311*a8de6003SAndroid Build Coastguard Worker
312*a8de6003SAndroid Build Coastguard Worker### Serializing and Deserializing Generic Types
313*a8de6003SAndroid Build Coastguard Worker
314*a8de6003SAndroid Build Coastguard WorkerWhen you call `toJson(obj)`, Gson calls `obj.getClass()` to get information on the fields to serialize. Similarly, you can typically pass `MyClass.class` object in the `fromJson(json, MyClass.class)` method. This works fine if the object is a non-generic type. However, if the object is of a generic type, then the Generic type information is lost because of Java Type Erasure. Here is an example illustrating the point:
315*a8de6003SAndroid Build Coastguard Worker
316*a8de6003SAndroid Build Coastguard Worker```java
317*a8de6003SAndroid Build Coastguard Workerclass Foo<T> {
318*a8de6003SAndroid Build Coastguard Worker  T value;
319*a8de6003SAndroid Build Coastguard Worker}
320*a8de6003SAndroid Build Coastguard WorkerGson gson = new Gson();
321*a8de6003SAndroid Build Coastguard WorkerFoo<Bar> foo = new Foo<Bar>();
322*a8de6003SAndroid Build Coastguard Workergson.toJson(foo); // May not serialize foo.value correctly
323*a8de6003SAndroid Build Coastguard Worker
324*a8de6003SAndroid Build Coastguard Workergson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
325*a8de6003SAndroid Build Coastguard Worker```
326*a8de6003SAndroid Build Coastguard Worker
327*a8de6003SAndroid Build Coastguard WorkerThe above code fails to interpret value as type Bar because Gson invokes `foo.getClass()` to get its class information, but this method returns a raw class, `Foo.class`. This means that Gson has no way of knowing that this is an object of type `Foo<Bar>`, and not just plain `Foo`.
328*a8de6003SAndroid Build Coastguard Worker
329*a8de6003SAndroid Build Coastguard WorkerYou can solve this problem by specifying the correct parameterized type for your generic type. You can do this by using the [`TypeToken`](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/reflect/TypeToken.html) class.
330*a8de6003SAndroid Build Coastguard Worker
331*a8de6003SAndroid Build Coastguard Worker```java
332*a8de6003SAndroid Build Coastguard WorkerType fooType = new TypeToken<Foo<Bar>>() {}.getType();
333*a8de6003SAndroid Build Coastguard Workergson.toJson(foo, fooType);
334*a8de6003SAndroid Build Coastguard Worker
335*a8de6003SAndroid Build Coastguard Workergson.fromJson(json, fooType);
336*a8de6003SAndroid Build Coastguard Worker```
337*a8de6003SAndroid Build Coastguard Worker
338*a8de6003SAndroid Build Coastguard WorkerThe idiom used to get `fooType` actually defines an anonymous local inner class containing a method `getType()` that returns the fully parameterized type.
339*a8de6003SAndroid Build Coastguard Worker
340*a8de6003SAndroid Build Coastguard Worker### Serializing and Deserializing Collection with Objects of Arbitrary Types
341*a8de6003SAndroid Build Coastguard Worker
342*a8de6003SAndroid Build Coastguard WorkerSometimes you are dealing with JSON array that contains mixed types. For example:
343*a8de6003SAndroid Build Coastguard Worker`['hello',5,{name:'GREETINGS',source:'guest'}]`
344*a8de6003SAndroid Build Coastguard Worker
345*a8de6003SAndroid Build Coastguard WorkerThe equivalent `Collection` containing this is:
346*a8de6003SAndroid Build Coastguard Worker
347*a8de6003SAndroid Build Coastguard Worker```java
348*a8de6003SAndroid Build Coastguard WorkerCollection collection = new ArrayList();
349*a8de6003SAndroid Build Coastguard Workercollection.add("hello");
350*a8de6003SAndroid Build Coastguard Workercollection.add(5);
351*a8de6003SAndroid Build Coastguard Workercollection.add(new Event("GREETINGS", "guest"));
352*a8de6003SAndroid Build Coastguard Worker```
353*a8de6003SAndroid Build Coastguard Worker
354*a8de6003SAndroid Build Coastguard Workerwhere the `Event` class is defined as:
355*a8de6003SAndroid Build Coastguard Worker
356*a8de6003SAndroid Build Coastguard Worker```java
357*a8de6003SAndroid Build Coastguard Workerclass Event {
358*a8de6003SAndroid Build Coastguard Worker  private String name;
359*a8de6003SAndroid Build Coastguard Worker  private String source;
360*a8de6003SAndroid Build Coastguard Worker  private Event(String name, String source) {
361*a8de6003SAndroid Build Coastguard Worker    this.name = name;
362*a8de6003SAndroid Build Coastguard Worker    this.source = source;
363*a8de6003SAndroid Build Coastguard Worker  }
364*a8de6003SAndroid Build Coastguard Worker}
365*a8de6003SAndroid Build Coastguard Worker```
366*a8de6003SAndroid Build Coastguard Worker
367*a8de6003SAndroid Build Coastguard WorkerYou can serialize the collection with Gson without doing anything specific: `toJson(collection)` would write out the desired output.
368*a8de6003SAndroid Build Coastguard Worker
369*a8de6003SAndroid Build Coastguard WorkerHowever, deserialization with `fromJson(json, Collection.class)` will not work since Gson has no way of knowing how to map the input to the types. Gson requires that you provide a genericised version of collection type in `fromJson()`. So, you have three options:
370*a8de6003SAndroid Build Coastguard Worker
371*a8de6003SAndroid Build Coastguard Worker1. Use Gson's parser API (low-level streaming parser or the DOM parser JsonParser) to parse the array elements and then use `Gson.fromJson()` on each of the array elements.This is the preferred approach. [Here is an example](extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java) that demonstrates how to do this.
372*a8de6003SAndroid Build Coastguard Worker
373*a8de6003SAndroid Build Coastguard Worker2. Register a type adapter for `Collection.class` that looks at each of the array members and maps them to appropriate objects. The disadvantage of this approach is that it will screw up deserialization of other collection types in Gson.
374*a8de6003SAndroid Build Coastguard Worker
375*a8de6003SAndroid Build Coastguard Worker3. Register a type adapter for `MyCollectionMemberType` and use `fromJson()` with `Collection<MyCollectionMemberType>`.
376*a8de6003SAndroid Build Coastguard Worker
377*a8de6003SAndroid Build Coastguard WorkerThis approach is practical only if the array appears as a top-level element or if you can change the field type holding the collection to be of type `Collection<MyCollectionMemberType>`.
378*a8de6003SAndroid Build Coastguard Worker
379*a8de6003SAndroid Build Coastguard Worker### Built-in Serializers and Deserializers
380*a8de6003SAndroid Build Coastguard Worker
381*a8de6003SAndroid Build Coastguard WorkerGson has built-in serializers and deserializers for commonly used classes whose default representation may be inappropriate, for instance
382*a8de6003SAndroid Build Coastguard Worker
383*a8de6003SAndroid Build Coastguard Worker* `java.net.URL` to match it with strings like `"https://github.com/google/gson/"`
384*a8de6003SAndroid Build Coastguard Worker* `java.net.URI` to match it with strings like `"/google/gson/"`
385*a8de6003SAndroid Build Coastguard Worker
386*a8de6003SAndroid Build Coastguard WorkerFor many more, see the internal class [`TypeAdapters`](gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java).
387*a8de6003SAndroid Build Coastguard Worker
388*a8de6003SAndroid Build Coastguard WorkerYou can also find source code for some commonly used classes such as JodaTime at [this page](https://sites.google.com/site/gson/gson-type-adapters-for-common-classes-1).
389*a8de6003SAndroid Build Coastguard Worker
390*a8de6003SAndroid Build Coastguard Worker### Custom Serialization and Deserialization
391*a8de6003SAndroid Build Coastguard Worker
392*a8de6003SAndroid Build Coastguard WorkerSometimes default representation is not what you want. This is often the case when dealing with library classes (DateTime, etc).
393*a8de6003SAndroid Build Coastguard WorkerGson allows you to register your own custom serializers and deserializers. This is done by defining two parts:
394*a8de6003SAndroid Build Coastguard Worker
395*a8de6003SAndroid Build Coastguard Worker* JSON Serializers: Need to define custom serialization for an object
396*a8de6003SAndroid Build Coastguard Worker* JSON Deserializers: Needed to define custom deserialization for a type
397*a8de6003SAndroid Build Coastguard Worker
398*a8de6003SAndroid Build Coastguard Worker* Instance Creators: Not needed if no-args constructor is available or a deserializer is registered
399*a8de6003SAndroid Build Coastguard Worker
400*a8de6003SAndroid Build Coastguard Worker```java
401*a8de6003SAndroid Build Coastguard WorkerGsonBuilder gson = new GsonBuilder();
402*a8de6003SAndroid Build Coastguard Workergson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
403*a8de6003SAndroid Build Coastguard Workergson.registerTypeAdapter(MyType.class, new MySerializer());
404*a8de6003SAndroid Build Coastguard Workergson.registerTypeAdapter(MyType.class, new MyDeserializer());
405*a8de6003SAndroid Build Coastguard Workergson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
406*a8de6003SAndroid Build Coastguard Worker```
407*a8de6003SAndroid Build Coastguard Worker
408*a8de6003SAndroid Build Coastguard Worker`registerTypeAdapter` call checks if the type adapter implements more than one of these interfaces and register it for all of them.
409*a8de6003SAndroid Build Coastguard Worker
410*a8de6003SAndroid Build Coastguard Worker#### Writing a Serializer
411*a8de6003SAndroid Build Coastguard Worker
412*a8de6003SAndroid Build Coastguard WorkerHere is an example of how to write a custom serializer for JodaTime `DateTime` class.
413*a8de6003SAndroid Build Coastguard Worker
414*a8de6003SAndroid Build Coastguard Worker```java
415*a8de6003SAndroid Build Coastguard Workerprivate class DateTimeSerializer implements JsonSerializer<DateTime> {
416*a8de6003SAndroid Build Coastguard Worker  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
417*a8de6003SAndroid Build Coastguard Worker    return new JsonPrimitive(src.toString());
418*a8de6003SAndroid Build Coastguard Worker  }
419*a8de6003SAndroid Build Coastguard Worker}
420*a8de6003SAndroid Build Coastguard Worker```
421*a8de6003SAndroid Build Coastguard Worker
422*a8de6003SAndroid Build Coastguard WorkerGson calls `serialize()` when it runs into a `DateTime` object during serialization.
423*a8de6003SAndroid Build Coastguard Worker
424*a8de6003SAndroid Build Coastguard Worker#### Writing a Deserializer
425*a8de6003SAndroid Build Coastguard Worker
426*a8de6003SAndroid Build Coastguard WorkerHere is an example of how to write a custom deserializer for JodaTime DateTime class.
427*a8de6003SAndroid Build Coastguard Worker
428*a8de6003SAndroid Build Coastguard Worker```java
429*a8de6003SAndroid Build Coastguard Workerprivate class DateTimeDeserializer implements JsonDeserializer<DateTime> {
430*a8de6003SAndroid Build Coastguard Worker  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
431*a8de6003SAndroid Build Coastguard Worker      throws JsonParseException {
432*a8de6003SAndroid Build Coastguard Worker    return new DateTime(json.getAsJsonPrimitive().getAsString());
433*a8de6003SAndroid Build Coastguard Worker  }
434*a8de6003SAndroid Build Coastguard Worker}
435*a8de6003SAndroid Build Coastguard Worker```
436*a8de6003SAndroid Build Coastguard Worker
437*a8de6003SAndroid Build Coastguard WorkerGson calls `deserialize` when it needs to deserialize a JSON string fragment into a DateTime object
438*a8de6003SAndroid Build Coastguard Worker
439*a8de6003SAndroid Build Coastguard Worker**Finer points with Serializers and Deserializers**
440*a8de6003SAndroid Build Coastguard Worker
441*a8de6003SAndroid Build Coastguard WorkerOften you want to register a single handler for all generic types corresponding to a raw type
442*a8de6003SAndroid Build Coastguard Worker
443*a8de6003SAndroid Build Coastguard Worker* For example, suppose you have an `Id` class for id representation/translation (i.e. an internal vs. external representation).
444*a8de6003SAndroid Build Coastguard Worker* `Id<T>` type that has same serialization for all generic types
445*a8de6003SAndroid Build Coastguard Worker  * Essentially write out the id value
446*a8de6003SAndroid Build Coastguard Worker* Deserialization is very similar but not exactly the same
447*a8de6003SAndroid Build Coastguard Worker  * Need to call `new Id(Class<T>, String)` which returns an instance of `Id<T>`
448*a8de6003SAndroid Build Coastguard Worker
449*a8de6003SAndroid Build Coastguard WorkerGson supports registering a single handler for this. You can also register a specific handler for a specific generic type (say `Id<RequiresSpecialHandling>` needed special handling).
450*a8de6003SAndroid Build Coastguard WorkerThe `Type` parameter for the `toJson()` and `fromJson()` contains the generic type information to help you write a single handler for all generic types corresponding to the same raw type.
451*a8de6003SAndroid Build Coastguard Worker
452*a8de6003SAndroid Build Coastguard Worker### Writing an Instance Creator
453*a8de6003SAndroid Build Coastguard Worker
454*a8de6003SAndroid Build Coastguard WorkerWhile deserializing an Object, Gson needs to create a default instance of the class.
455*a8de6003SAndroid Build Coastguard WorkerWell-behaved classes that are meant for serialization and deserialization should have a no-argument constructor.
456*a8de6003SAndroid Build Coastguard Worker
457*a8de6003SAndroid Build Coastguard Worker* Doesn't matter whether public or private
458*a8de6003SAndroid Build Coastguard Worker
459*a8de6003SAndroid Build Coastguard WorkerTypically, Instance Creators are needed when you are dealing with a library class that does NOT define a no-argument constructor
460*a8de6003SAndroid Build Coastguard Worker
461*a8de6003SAndroid Build Coastguard Worker**Instance Creator Example**
462*a8de6003SAndroid Build Coastguard Worker
463*a8de6003SAndroid Build Coastguard Worker```java
464*a8de6003SAndroid Build Coastguard Workerprivate class MoneyInstanceCreator implements InstanceCreator<Money> {
465*a8de6003SAndroid Build Coastguard Worker  public Money createInstance(Type type) {
466*a8de6003SAndroid Build Coastguard Worker    return new Money("1000000", CurrencyCode.USD);
467*a8de6003SAndroid Build Coastguard Worker  }
468*a8de6003SAndroid Build Coastguard Worker}
469*a8de6003SAndroid Build Coastguard Worker```
470*a8de6003SAndroid Build Coastguard Worker
471*a8de6003SAndroid Build Coastguard WorkerType could be of a corresponding generic type
472*a8de6003SAndroid Build Coastguard Worker
473*a8de6003SAndroid Build Coastguard Worker* Very useful to invoke constructors which need specific generic type information
474*a8de6003SAndroid Build Coastguard Worker* For example, if the `Id` class stores the class for which the Id is being created
475*a8de6003SAndroid Build Coastguard Worker
476*a8de6003SAndroid Build Coastguard Worker#### InstanceCreator for a Parameterized Type
477*a8de6003SAndroid Build Coastguard Worker
478*a8de6003SAndroid Build Coastguard WorkerSometimes the type that you are trying to instantiate is a parameterized type. Generally, this is not a problem since the actual instance is of raw type. Here is an example:
479*a8de6003SAndroid Build Coastguard Worker
480*a8de6003SAndroid Build Coastguard Worker```java
481*a8de6003SAndroid Build Coastguard Workerclass MyList<T> extends ArrayList<T> {
482*a8de6003SAndroid Build Coastguard Worker}
483*a8de6003SAndroid Build Coastguard Worker
484*a8de6003SAndroid Build Coastguard Workerclass MyListInstanceCreator implements InstanceCreator<MyList<?>> {
485*a8de6003SAndroid Build Coastguard Worker  @SuppressWarnings("unchecked")
486*a8de6003SAndroid Build Coastguard Worker  public MyList<?> createInstance(Type type) {
487*a8de6003SAndroid Build Coastguard Worker    // No need to use a parameterized list since the actual instance will have the raw type anyway.
488*a8de6003SAndroid Build Coastguard Worker    return new MyList();
489*a8de6003SAndroid Build Coastguard Worker  }
490*a8de6003SAndroid Build Coastguard Worker}
491*a8de6003SAndroid Build Coastguard Worker```
492*a8de6003SAndroid Build Coastguard Worker
493*a8de6003SAndroid Build Coastguard WorkerHowever, sometimes you do need to create instance based on the actual parameterized type. In this case, you can use the type parameter being passed to the `createInstance` method. Here is an example:
494*a8de6003SAndroid Build Coastguard Worker
495*a8de6003SAndroid Build Coastguard Worker```java
496*a8de6003SAndroid Build Coastguard Workerpublic class Id<T> {
497*a8de6003SAndroid Build Coastguard Worker  private final Class<T> classOfId;
498*a8de6003SAndroid Build Coastguard Worker  private final long value;
499*a8de6003SAndroid Build Coastguard Worker  public Id(Class<T> classOfId, long value) {
500*a8de6003SAndroid Build Coastguard Worker    this.classOfId = classOfId;
501*a8de6003SAndroid Build Coastguard Worker    this.value = value;
502*a8de6003SAndroid Build Coastguard Worker  }
503*a8de6003SAndroid Build Coastguard Worker}
504*a8de6003SAndroid Build Coastguard Worker
505*a8de6003SAndroid Build Coastguard Workerclass IdInstanceCreator implements InstanceCreator<Id<?>> {
506*a8de6003SAndroid Build Coastguard Worker  public Id<?> createInstance(Type type) {
507*a8de6003SAndroid Build Coastguard Worker    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
508*a8de6003SAndroid Build Coastguard Worker    Type idType = typeParameters[0]; // Id has only one parameterized type T
509*a8de6003SAndroid Build Coastguard Worker    return new Id((Class)idType, 0L);
510*a8de6003SAndroid Build Coastguard Worker  }
511*a8de6003SAndroid Build Coastguard Worker}
512*a8de6003SAndroid Build Coastguard Worker```
513*a8de6003SAndroid Build Coastguard Worker
514*a8de6003SAndroid Build Coastguard WorkerIn the above example, an instance of the Id class can not be created without actually passing in the actual type for the parameterized type. We solve this problem by using the passed method parameter, `type`. The `type` object in this case is the Java parameterized type representation of `Id<Foo>` where the actual instance should be bound to `Id<Foo>`. Since `Id` class has just one parameterized type parameter, `T`, we use the zeroth element of the type array returned by `getActualTypeArgument()` which will hold `Foo.class` in this case.
515*a8de6003SAndroid Build Coastguard Worker
516*a8de6003SAndroid Build Coastguard Worker### Compact Vs. Pretty Printing for JSON Output Format
517*a8de6003SAndroid Build Coastguard Worker
518*a8de6003SAndroid Build Coastguard WorkerThe default JSON output that is provided by Gson is a compact JSON format. This means that there will not be any whitespace in the output JSON structure. Therefore, there will be no whitespace between field names and its value, object fields, and objects within arrays in the JSON output. As well, "null" fields will be ignored in the output (NOTE: null values will still be included in collections/arrays of objects). See the [Null Object Support](#null-object-support) section for information on configure Gson to output all null values.
519*a8de6003SAndroid Build Coastguard Worker
520*a8de6003SAndroid Build Coastguard WorkerIf you would like to use the Pretty Print feature, you must configure your `Gson` instance using the `GsonBuilder`. The `JsonFormatter` is not exposed through our public API, so the client is unable to configure the default print settings/margins for the JSON output. For now, we only provide a default `JsonPrintFormatter` that has default line length of 80 character, 2 character indentation, and 4 character right margin.
521*a8de6003SAndroid Build Coastguard Worker
522*a8de6003SAndroid Build Coastguard WorkerThe following is an example shows how to configure a `Gson` instance to use the default `JsonPrintFormatter` instead of the `JsonCompactFormatter`:
523*a8de6003SAndroid Build Coastguard Worker
524*a8de6003SAndroid Build Coastguard Worker```java
525*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().setPrettyPrinting().create();
526*a8de6003SAndroid Build Coastguard WorkerString jsonOutput = gson.toJson(someObject);
527*a8de6003SAndroid Build Coastguard Worker```
528*a8de6003SAndroid Build Coastguard Worker
529*a8de6003SAndroid Build Coastguard Worker### Null Object Support
530*a8de6003SAndroid Build Coastguard Worker
531*a8de6003SAndroid Build Coastguard WorkerThe default behaviour that is implemented in Gson is that `null` object fields are ignored. This allows for a more compact output format; however, the client must define a default value for these fields as the JSON format is converted back into its Java form.
532*a8de6003SAndroid Build Coastguard Worker
533*a8de6003SAndroid Build Coastguard WorkerHere's how you would configure a `Gson` instance to output null:
534*a8de6003SAndroid Build Coastguard Worker
535*a8de6003SAndroid Build Coastguard Worker```java
536*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().serializeNulls().create();
537*a8de6003SAndroid Build Coastguard Worker```
538*a8de6003SAndroid Build Coastguard Worker
539*a8de6003SAndroid Build Coastguard WorkerNOTE: when serializing `null`s with Gson, it will add a `JsonNull` element to the `JsonElement` structure. Therefore, this object can be used in custom serialization/deserialization.
540*a8de6003SAndroid Build Coastguard Worker
541*a8de6003SAndroid Build Coastguard WorkerHere's an example:
542*a8de6003SAndroid Build Coastguard Worker
543*a8de6003SAndroid Build Coastguard Worker```java
544*a8de6003SAndroid Build Coastguard Workerpublic class Foo {
545*a8de6003SAndroid Build Coastguard Worker  private final String s;
546*a8de6003SAndroid Build Coastguard Worker  private final int i;
547*a8de6003SAndroid Build Coastguard Worker
548*a8de6003SAndroid Build Coastguard Worker  public Foo() {
549*a8de6003SAndroid Build Coastguard Worker    this(null, 5);
550*a8de6003SAndroid Build Coastguard Worker  }
551*a8de6003SAndroid Build Coastguard Worker
552*a8de6003SAndroid Build Coastguard Worker  public Foo(String s, int i) {
553*a8de6003SAndroid Build Coastguard Worker    this.s = s;
554*a8de6003SAndroid Build Coastguard Worker    this.i = i;
555*a8de6003SAndroid Build Coastguard Worker  }
556*a8de6003SAndroid Build Coastguard Worker}
557*a8de6003SAndroid Build Coastguard Worker
558*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().serializeNulls().create();
559*a8de6003SAndroid Build Coastguard WorkerFoo foo = new Foo();
560*a8de6003SAndroid Build Coastguard WorkerString json = gson.toJson(foo);
561*a8de6003SAndroid Build Coastguard WorkerSystem.out.println(json);
562*a8de6003SAndroid Build Coastguard Worker
563*a8de6003SAndroid Build Coastguard Workerjson = gson.toJson(null);
564*a8de6003SAndroid Build Coastguard WorkerSystem.out.println(json);
565*a8de6003SAndroid Build Coastguard Worker```
566*a8de6003SAndroid Build Coastguard Worker
567*a8de6003SAndroid Build Coastguard WorkerThe output is:
568*a8de6003SAndroid Build Coastguard Worker
569*a8de6003SAndroid Build Coastguard Worker```json
570*a8de6003SAndroid Build Coastguard Worker{"s":null,"i":5}
571*a8de6003SAndroid Build Coastguard Workernull
572*a8de6003SAndroid Build Coastguard Worker```
573*a8de6003SAndroid Build Coastguard Worker
574*a8de6003SAndroid Build Coastguard Worker### Versioning Support
575*a8de6003SAndroid Build Coastguard Worker
576*a8de6003SAndroid Build Coastguard WorkerMultiple versions of the same object can be maintained by using [@Since](gson/src/main/java/com/google/gson/annotations/Since.java) annotation. This annotation can be used on Classes, Fields and, in a future release, Methods. In order to leverage this feature, you must configure your `Gson` instance to ignore any field/object that is greater than some version number. If no version is set on the `Gson` instance then it will serialize and deserialize all fields and classes regardless of the version.
577*a8de6003SAndroid Build Coastguard Worker
578*a8de6003SAndroid Build Coastguard Worker```java
579*a8de6003SAndroid Build Coastguard Workerpublic class VersionedClass {
580*a8de6003SAndroid Build Coastguard Worker  @Since(1.1) private final String newerField;
581*a8de6003SAndroid Build Coastguard Worker  @Since(1.0) private final String newField;
582*a8de6003SAndroid Build Coastguard Worker  private final String field;
583*a8de6003SAndroid Build Coastguard Worker
584*a8de6003SAndroid Build Coastguard Worker  public VersionedClass() {
585*a8de6003SAndroid Build Coastguard Worker    this.newerField = "newer";
586*a8de6003SAndroid Build Coastguard Worker    this.newField = "new";
587*a8de6003SAndroid Build Coastguard Worker    this.field = "old";
588*a8de6003SAndroid Build Coastguard Worker  }
589*a8de6003SAndroid Build Coastguard Worker}
590*a8de6003SAndroid Build Coastguard Worker
591*a8de6003SAndroid Build Coastguard WorkerVersionedClass versionedObject = new VersionedClass();
592*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().setVersion(1.0).create();
593*a8de6003SAndroid Build Coastguard WorkerString jsonOutput = gson.toJson(versionedObject);
594*a8de6003SAndroid Build Coastguard WorkerSystem.out.println(jsonOutput);
595*a8de6003SAndroid Build Coastguard WorkerSystem.out.println();
596*a8de6003SAndroid Build Coastguard Worker
597*a8de6003SAndroid Build Coastguard Workergson = new Gson();
598*a8de6003SAndroid Build Coastguard WorkerjsonOutput = gson.toJson(versionedObject);
599*a8de6003SAndroid Build Coastguard WorkerSystem.out.println(jsonOutput);
600*a8de6003SAndroid Build Coastguard Worker```
601*a8de6003SAndroid Build Coastguard Worker
602*a8de6003SAndroid Build Coastguard WorkerThe output is:
603*a8de6003SAndroid Build Coastguard Worker
604*a8de6003SAndroid Build Coastguard Worker```json
605*a8de6003SAndroid Build Coastguard Worker{"newField":"new","field":"old"}
606*a8de6003SAndroid Build Coastguard Worker
607*a8de6003SAndroid Build Coastguard Worker{"newerField":"newer","newField":"new","field":"old"}
608*a8de6003SAndroid Build Coastguard Worker```
609*a8de6003SAndroid Build Coastguard Worker
610*a8de6003SAndroid Build Coastguard Worker### Excluding Fields From Serialization and Deserialization
611*a8de6003SAndroid Build Coastguard Worker
612*a8de6003SAndroid Build Coastguard WorkerGson supports numerous mechanisms for excluding top-level classes, fields and field types. Below are pluggable mechanisms that allow field and class exclusion. If none of the below mechanisms satisfy your needs then you can always use [custom serializers and deserializers](#custom-serialization-and-deserialization).
613*a8de6003SAndroid Build Coastguard Worker
614*a8de6003SAndroid Build Coastguard Worker#### Java Modifier Exclusion
615*a8de6003SAndroid Build Coastguard Worker
616*a8de6003SAndroid Build Coastguard WorkerBy default, if you mark a field as `transient`, it will be excluded. As well, if a field is marked as `static` then by default it will be excluded. If you want to include some transient fields then you can do the following:
617*a8de6003SAndroid Build Coastguard Worker
618*a8de6003SAndroid Build Coastguard Worker```java
619*a8de6003SAndroid Build Coastguard Workerimport java.lang.reflect.Modifier;
620*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder()
621*a8de6003SAndroid Build Coastguard Worker    .excludeFieldsWithModifiers(Modifier.STATIC)
622*a8de6003SAndroid Build Coastguard Worker    .create();
623*a8de6003SAndroid Build Coastguard Worker```
624*a8de6003SAndroid Build Coastguard Worker
625*a8de6003SAndroid Build Coastguard WorkerNOTE: you can give any number of the `Modifier` constants to the `excludeFieldsWithModifiers` method. For example:
626*a8de6003SAndroid Build Coastguard Worker
627*a8de6003SAndroid Build Coastguard Worker```java
628*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder()
629*a8de6003SAndroid Build Coastguard Worker    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
630*a8de6003SAndroid Build Coastguard Worker    .create();
631*a8de6003SAndroid Build Coastguard Worker```
632*a8de6003SAndroid Build Coastguard Worker
633*a8de6003SAndroid Build Coastguard Worker#### Gson's `@Expose`
634*a8de6003SAndroid Build Coastguard Worker
635*a8de6003SAndroid Build Coastguard WorkerThis feature provides a way where you can mark certain fields of your objects to be excluded for consideration for serialization and deserialization to JSON. To use this annotation, you must create Gson by using `new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()`. The Gson instance created will exclude all fields in a class that are not marked with `@Expose` annotation.
636*a8de6003SAndroid Build Coastguard Worker
637*a8de6003SAndroid Build Coastguard Worker#### User Defined Exclusion Strategies
638*a8de6003SAndroid Build Coastguard Worker
639*a8de6003SAndroid Build Coastguard WorkerIf the above mechanisms for excluding fields and class type do not work for you then you can always write your own exclusion strategy and plug it into Gson. See the [`ExclusionStrategy`](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/ExclusionStrategy.html) JavaDoc for more information.
640*a8de6003SAndroid Build Coastguard Worker
641*a8de6003SAndroid Build Coastguard WorkerThe following example shows how to exclude fields marked with a specific `@Foo` annotation and excludes top-level types (or declared field type) of class `String`.
642*a8de6003SAndroid Build Coastguard Worker
643*a8de6003SAndroid Build Coastguard Worker```java
644*a8de6003SAndroid Build Coastguard Worker@Retention(RetentionPolicy.RUNTIME)
645*a8de6003SAndroid Build Coastguard Worker@Target({ElementType.FIELD})
646*a8de6003SAndroid Build Coastguard Workerpublic @interface Foo {
647*a8de6003SAndroid Build Coastguard Worker  // Field tag only annotation
648*a8de6003SAndroid Build Coastguard Worker}
649*a8de6003SAndroid Build Coastguard Worker
650*a8de6003SAndroid Build Coastguard Workerpublic class SampleObjectForTest {
651*a8de6003SAndroid Build Coastguard Worker  @Foo private final int annotatedField;
652*a8de6003SAndroid Build Coastguard Worker  private final String stringField;
653*a8de6003SAndroid Build Coastguard Worker  private final long longField;
654*a8de6003SAndroid Build Coastguard Worker  private final Class<?> clazzField;
655*a8de6003SAndroid Build Coastguard Worker
656*a8de6003SAndroid Build Coastguard Worker  public SampleObjectForTest() {
657*a8de6003SAndroid Build Coastguard Worker    annotatedField = 5;
658*a8de6003SAndroid Build Coastguard Worker    stringField = "someDefaultValue";
659*a8de6003SAndroid Build Coastguard Worker    longField = 1234;
660*a8de6003SAndroid Build Coastguard Worker  }
661*a8de6003SAndroid Build Coastguard Worker}
662*a8de6003SAndroid Build Coastguard Worker
663*a8de6003SAndroid Build Coastguard Workerpublic class MyExclusionStrategy implements ExclusionStrategy {
664*a8de6003SAndroid Build Coastguard Worker  private final Class<?> typeToSkip;
665*a8de6003SAndroid Build Coastguard Worker
666*a8de6003SAndroid Build Coastguard Worker  private MyExclusionStrategy(Class<?> typeToSkip) {
667*a8de6003SAndroid Build Coastguard Worker    this.typeToSkip = typeToSkip;
668*a8de6003SAndroid Build Coastguard Worker  }
669*a8de6003SAndroid Build Coastguard Worker
670*a8de6003SAndroid Build Coastguard Worker  public boolean shouldSkipClass(Class<?> clazz) {
671*a8de6003SAndroid Build Coastguard Worker    return (clazz == typeToSkip);
672*a8de6003SAndroid Build Coastguard Worker  }
673*a8de6003SAndroid Build Coastguard Worker
674*a8de6003SAndroid Build Coastguard Worker  public boolean shouldSkipField(FieldAttributes f) {
675*a8de6003SAndroid Build Coastguard Worker    return f.getAnnotation(Foo.class) != null;
676*a8de6003SAndroid Build Coastguard Worker  }
677*a8de6003SAndroid Build Coastguard Worker}
678*a8de6003SAndroid Build Coastguard Worker
679*a8de6003SAndroid Build Coastguard Workerpublic static void main(String[] args) {
680*a8de6003SAndroid Build Coastguard Worker  Gson gson = new GsonBuilder()
681*a8de6003SAndroid Build Coastguard Worker      .setExclusionStrategies(new MyExclusionStrategy(String.class))
682*a8de6003SAndroid Build Coastguard Worker      .serializeNulls()
683*a8de6003SAndroid Build Coastguard Worker      .create();
684*a8de6003SAndroid Build Coastguard Worker  SampleObjectForTest src = new SampleObjectForTest();
685*a8de6003SAndroid Build Coastguard Worker  String json = gson.toJson(src);
686*a8de6003SAndroid Build Coastguard Worker  System.out.println(json);
687*a8de6003SAndroid Build Coastguard Worker}
688*a8de6003SAndroid Build Coastguard Worker```
689*a8de6003SAndroid Build Coastguard Worker
690*a8de6003SAndroid Build Coastguard WorkerThe output is:
691*a8de6003SAndroid Build Coastguard Worker
692*a8de6003SAndroid Build Coastguard Worker```json
693*a8de6003SAndroid Build Coastguard Worker{"longField":1234}
694*a8de6003SAndroid Build Coastguard Worker```
695*a8de6003SAndroid Build Coastguard Worker
696*a8de6003SAndroid Build Coastguard Worker### JSON Field Naming Support
697*a8de6003SAndroid Build Coastguard Worker
698*a8de6003SAndroid Build Coastguard WorkerGson supports some pre-defined field naming policies to convert the standard Java field names (i.e., camel cased names starting with lower case --- `sampleFieldNameInJava`) to a JSON field name (i.e., `sample_field_name_in_java` or `SampleFieldNameInJava`). See the [FieldNamingPolicy](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/FieldNamingPolicy.html) class for information on the pre-defined naming policies.
699*a8de6003SAndroid Build Coastguard Worker
700*a8de6003SAndroid Build Coastguard WorkerIt also has an annotation based strategy to allows clients to define custom names on a per field basis. Note, that the annotation based strategy has field name validation which will raise "Runtime" exceptions if an invalid field name is provided as the annotation value.
701*a8de6003SAndroid Build Coastguard Worker
702*a8de6003SAndroid Build Coastguard WorkerThe following is an example of how to use both Gson naming policy features:
703*a8de6003SAndroid Build Coastguard Worker
704*a8de6003SAndroid Build Coastguard Worker```java
705*a8de6003SAndroid Build Coastguard Workerprivate class SomeObject {
706*a8de6003SAndroid Build Coastguard Worker  @SerializedName("custom_naming") private final String someField;
707*a8de6003SAndroid Build Coastguard Worker  private final String someOtherField;
708*a8de6003SAndroid Build Coastguard Worker
709*a8de6003SAndroid Build Coastguard Worker  public SomeObject(String a, String b) {
710*a8de6003SAndroid Build Coastguard Worker    this.someField = a;
711*a8de6003SAndroid Build Coastguard Worker    this.someOtherField = b;
712*a8de6003SAndroid Build Coastguard Worker  }
713*a8de6003SAndroid Build Coastguard Worker}
714*a8de6003SAndroid Build Coastguard Worker
715*a8de6003SAndroid Build Coastguard WorkerSomeObject someObject = new SomeObject("first", "second");
716*a8de6003SAndroid Build Coastguard WorkerGson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
717*a8de6003SAndroid Build Coastguard WorkerString jsonRepresentation = gson.toJson(someObject);
718*a8de6003SAndroid Build Coastguard WorkerSystem.out.println(jsonRepresentation);
719*a8de6003SAndroid Build Coastguard Worker```
720*a8de6003SAndroid Build Coastguard Worker
721*a8de6003SAndroid Build Coastguard WorkerThe output is:
722*a8de6003SAndroid Build Coastguard Worker
723*a8de6003SAndroid Build Coastguard Worker```json
724*a8de6003SAndroid Build Coastguard Worker{"custom_naming":"first","SomeOtherField":"second"}
725*a8de6003SAndroid Build Coastguard Worker```
726*a8de6003SAndroid Build Coastguard Worker
727*a8de6003SAndroid Build Coastguard WorkerIf you have a need for custom naming policy ([see this discussion](https://groups.google.com/group/google-gson/browse_thread/thread/cb441a2d717f6892)), you can use the [@SerializedName](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/annotations/SerializedName.html) annotation.
728*a8de6003SAndroid Build Coastguard Worker
729*a8de6003SAndroid Build Coastguard Worker### Sharing State Across Custom Serializers and Deserializers
730*a8de6003SAndroid Build Coastguard Worker
731*a8de6003SAndroid Build Coastguard WorkerSometimes you need to share state across custom serializers/deserializers ([see this discussion](https://groups.google.com/group/google-gson/browse_thread/thread/2850010691ea09fb)). You can use the following three strategies to accomplish this:
732*a8de6003SAndroid Build Coastguard Worker
733*a8de6003SAndroid Build Coastguard Worker1. Store shared state in static fields
734*a8de6003SAndroid Build Coastguard Worker2. Declare the serializer/deserializer as inner classes of a parent type, and use the instance fields of parent type to store shared state
735*a8de6003SAndroid Build Coastguard Worker3. Use Java `ThreadLocal`
736*a8de6003SAndroid Build Coastguard Worker
737*a8de6003SAndroid Build Coastguard Worker1 and 2 are not thread-safe options, but 3 is.
738*a8de6003SAndroid Build Coastguard Worker
739*a8de6003SAndroid Build Coastguard Worker### Streaming
740*a8de6003SAndroid Build Coastguard Worker
741*a8de6003SAndroid Build Coastguard WorkerIn addition Gson's object model and data binding, you can use Gson to read from and write to a [stream](https://sites.google.com/site/gson/streaming). You can also combine streaming and object model access to get the best of both approaches.
742*a8de6003SAndroid Build Coastguard Worker
743*a8de6003SAndroid Build Coastguard Worker## Issues in Designing Gson
744*a8de6003SAndroid Build Coastguard Worker
745*a8de6003SAndroid Build Coastguard WorkerSee the [Gson design document](GsonDesignDocument.md "Gson design document") for a discussion of issues we faced while designing Gson. It also include a comparison of Gson with other Java libraries that can be used for JSON conversion.
746*a8de6003SAndroid Build Coastguard Worker
747*a8de6003SAndroid Build Coastguard Worker## Future Enhancements to Gson
748*a8de6003SAndroid Build Coastguard Worker
749*a8de6003SAndroid Build Coastguard WorkerFor the latest list of proposed enhancements or if you'd like to suggest new ones, see the [Issues section](https://github.com/google/gson/issues) under the project website.
750