xref: /aosp_15_r20/external/gson/UserGuide.md (revision a8de600362638ea28fd6cb3225451dc706d269bb)
1# Gson User Guide
2
31. [Overview](#overview)
42. [Goals for Gson](#goals-for-gson)
53. [Gson Performance and Scalability](#gson-performance-and-scalability)
64. [Gson Users](#gson-users)
75. [Using Gson](#using-gson)
8   * [Using Gson with Gradle/Android](#using-gson-with-gradleandroid)
9   * [Using Gson with Maven](#using-gson-with-maven)
10   * [Primitives Examples](#primitives-examples)
11   * [Object Examples](#object-examples)
12   * [Finer Points with Objects](#finer-points-with-objects)
13   * [Nested Classes (including Inner Classes)](#nested-classes-including-inner-classes)
14   * [Array Examples](#array-examples)
15   * [Collections Examples](#collections-examples)
16     * [Collections Limitations](#collections-limitations)
17   * [Maps Examples](#maps-examples)
18   * [Serializing and Deserializing Generic Types](#serializing-and-deserializing-generic-types)
19   * [Serializing and Deserializing Collection with Objects of Arbitrary Types](#serializing-and-deserializing-collection-with-objects-of-arbitrary-types)
20   * [Built-in Serializers and Deserializers](#built-in-serializers-and-deserializers)
21   * [Custom Serialization and Deserialization](#custom-serialization-and-deserialization)
22     * [Writing a Serializer](#writing-a-serializer)
23     * [Writing a Deserializer](#writing-a-deserializer)
24   * [Writing an Instance Creator](#writing-an-instance-creator)
25     * [InstanceCreator for a Parameterized Type](#instancecreator-for-a-parameterized-type)
26   * [Compact Vs. Pretty Printing for JSON Output Format](#compact-vs-pretty-printing-for-json-output-format)
27   * [Null Object Support](#null-object-support)
28   * [Versioning Support](#versioning-support)
29   * [Excluding Fields From Serialization and Deserialization](#excluding-fields-from-serialization-and-deserialization)
30     * [Java Modifier Exclusion](#java-modifier-exclusion)
31     * [Gson's `@Expose`](#gsons-expose)
32     * [User Defined Exclusion Strategies](#user-defined-exclusion-strategies)
33   * [JSON Field Naming Support](#json-field-naming-support)
34   * [Sharing State Across Custom Serializers and Deserializers](#sharing-state-across-custom-serializers-and-deserializers)
35   * [Streaming](#streaming)
366. [Issues in Designing Gson](#issues-in-designing-gson)
377. [Future Enhancements to Gson](#future-enhancements-to-gson)
38
39## Overview
40
41Gson 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
43Gson can work with arbitrary Java objects including pre-existing objects that you do not have source code of.
44
45## Goals for Gson
46
47* Provide easy to use mechanisms like `toString()` and constructor (factory method) to convert Java to JSON and vice-versa
48* Allow pre-existing unmodifiable objects to be converted to and from JSON
49* Allow custom representations for objects
50* Support arbitrarily complex objects
51* Generate compact and readable JSON output
52
53## Gson Performance and Scalability
54
55Here 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
57* Strings: Deserialized strings of over 25MB without any problems (see `disabled_testStringDeserializationPerformance` method in `PerformanceTest`)
58* Large collections:
59  * Serialized a collection of 1.4 million objects (see `disabled_testLargeCollectionSerialization` method in `PerformanceTest`)
60  * Deserialized a collection of 87,000 objects (see `disabled_testLargeCollectionDeserialization` in `PerformanceTest`)
61* Gson 1.4 raised the deserialization limit for byte arrays and collection to over 11MB from 80KB.
62
63Note: Delete the `disabled_` prefix to run these tests. We use this prefix to prevent running these tests every time we run JUnit tests.
64
65## Gson Users
66
67Gson 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
69## Using Gson
70
71The 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
73The 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
75## Using Gson with Gradle/Android
76
77```gradle
78dependencies {
79    implementation 'com.google.code.gson:gson:2.10.1'
80}
81```
82
83## Using Gson with Maven
84
85To use Gson with Maven2/3, you can use the Gson version available in Maven Central by adding the following dependency:
86
87```xml
88<dependencies>
89    <!--  Gson: Java to JSON conversion -->
90    <dependency>
91      <groupId>com.google.code.gson</groupId>
92      <artifactId>gson</artifactId>
93      <version>2.10.1</version>
94      <scope>compile</scope>
95    </dependency>
96</dependencies>
97```
98
99That is it, now your Maven project is Gson enabled.
100
101### Primitives Examples
102
103```java
104// Serialization
105Gson gson = new Gson();
106gson.toJson(1);            // ==> 1
107gson.toJson("abcd");       // ==> "abcd"
108gson.toJson(new Long(10)); // ==> 10
109int[] values = { 1 };
110gson.toJson(values);       // ==> [1]
111
112// Deserialization
113int i = gson.fromJson("1", int.class);
114Integer intObj = gson.fromJson("1", Integer.class);
115Long longObj = gson.fromJson("1", Long.class);
116Boolean boolObj = gson.fromJson("false", Boolean.class);
117String str = gson.fromJson("\"abc\"", String.class);
118String[] strArray = gson.fromJson("[\"abc\"]", String[].class);
119```
120
121### Object Examples
122
123```java
124class BagOfPrimitives {
125  private int value1 = 1;
126  private String value2 = "abc";
127  private transient int value3 = 3;
128  BagOfPrimitives() {
129    // no-args constructor
130  }
131}
132
133// Serialization
134BagOfPrimitives obj = new BagOfPrimitives();
135Gson gson = new Gson();
136String json = gson.toJson(obj);
137
138// ==> json is {"value1":1,"value2":"abc"}
139```
140
141Note that you can not serialize objects with circular references since that will result in infinite recursion.
142
143```java
144// Deserialization
145BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
146// ==> obj2 is just like obj
147```
148
149#### **Finer Points with Objects**
150
151* It is perfectly fine (and recommended) to use private fields.
152* 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* If a field is marked transient, (by default) it is ignored and not included in the JSON serialization or deserialization.
154* This implementation handles nulls correctly.
155  * While serializing, a null field is omitted from the output.
156  * 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* If a field is _synthetic_, it is ignored and not included in JSON serialization or deserialization.
158* Fields corresponding to the outer classes in inner classes are ignored and not included in serialization or deserialization.
159* 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
161### Nested Classes (including Inner Classes)
162
163Gson can serialize static nested classes quite easily.
164
165Gson 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
167```java
168public class A {
169  public String a;
170
171  class B {
172
173    public String b;
174
175    public B() {
176      // No args constructor for B
177    }
178  }
179}
180```
181
182**NOTE**: The above class B can not (by default) be serialized with Gson.
183
184Gson 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
186```java
187public class InstanceCreatorForB implements InstanceCreator<A.B> {
188  private final A a;
189  public InstanceCreatorForB(A a)  {
190    this.a = a;
191  }
192  public A.B createInstance(Type type) {
193    return a.new B();
194  }
195}
196```
197
198The above is possible, but not recommended.
199
200### Array Examples
201
202```java
203Gson gson = new Gson();
204int[] ints = {1, 2, 3, 4, 5};
205String[] strings = {"abc", "def", "ghi"};
206
207// Serialization
208gson.toJson(ints);     // ==> [1,2,3,4,5]
209gson.toJson(strings);  // ==> ["abc", "def", "ghi"]
210
211// Deserialization
212int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
213// ==> ints2 will be same as ints
214```
215
216We also support multi-dimensional arrays, with arbitrarily complex element types.
217
218### Collections Examples
219
220```java
221Gson gson = new Gson();
222Collection<Integer> ints = Arrays.asList(1,2,3,4,5);
223
224// Serialization
225String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]
226
227// Deserialization
228TypeToken<Collection<Integer>> collectionType = new TypeToken<Collection<Integer>>(){};
229// Note: For older Gson versions it is necessary to use `collectionType.getType()` as argument below,
230// this is however not type-safe and care must be taken to specify the correct type for the local variable
231Collection<Integer> ints2 = gson.fromJson(json, collectionType);
232// ==> ints2 is same as ints
233```
234
235Fairly hideous: note how we define the type of collection.
236Unfortunately, there is no way to get around this in Java.
237
238#### Collections Limitations
239
240Gson 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.
241This makes sense, and is rarely a problem when following good Java coding practices.
242
243### Maps Examples
244
245Gson 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
247```java
248Gson gson = new Gson();
249Map<String, String> stringMap = new LinkedHashMap<>();
250stringMap.put("key", "value");
251stringMap.put(null, "null-entry");
252
253// Serialization
254String json = gson.toJson(stringMap); // ==> json is {"key":"value","null":"null-entry"}
255
256Map<Integer, Integer> intMap = new LinkedHashMap<>();
257intMap.put(2, 4);
258intMap.put(3, 6);
259
260// Serialization
261String json = gson.toJson(intMap); // ==> json is {"2":4,"3":6}
262```
263
264For 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
266```java
267Gson gson = new Gson();
268TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
269String json = "{\"key\": \"value\"}";
270
271// Deserialization
272// Note: For older Gson versions it is necessary to use `mapType.getType()` as argument below,
273// this is however not type-safe and care must be taken to specify the correct type for the local variable
274Map<String, String> stringMap = gson.fromJson(json, mapType);
275// ==> stringMap is {key=value}
276```
277
278Gson 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
280```java
281class PersonName {
282  String firstName;
283  String lastName;
284
285  PersonName(String firstName, String lastName) {
286    this.firstName = firstName;
287    this.lastName = lastName;
288  }
289
290  // ... equals and hashCode
291}
292
293Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
294Map<PersonName, Integer> complexMap = new LinkedHashMap<>();
295complexMap.put(new PersonName("John", "Doe"), 30);
296complexMap.put(new PersonName("Jane", "Doe"), 35);
297
298// Serialization; complex map is serialized as a JSON array containing key-value pairs (as JSON arrays)
299String json = gson.toJson(complexMap);
300// ==> json is [[{"firstName":"John","lastName":"Doe"},30],[{"firstName":"Jane","lastName":"Doe"},35]]
301
302Map<String, String> stringMap = new LinkedHashMap<>();
303stringMap.put("key", "value");
304// Serialization; non-complex map is serialized as a regular JSON object
305String json = gson.toJson(stringMap); // json is {"key":"value"}
306```
307
308**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
310Note 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
312### Serializing and Deserializing Generic Types
313
314When 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
316```java
317class Foo<T> {
318  T value;
319}
320Gson gson = new Gson();
321Foo<Bar> foo = new Foo<Bar>();
322gson.toJson(foo); // May not serialize foo.value correctly
323
324gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
325```
326
327The 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
329You 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
331```java
332Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
333gson.toJson(foo, fooType);
334
335gson.fromJson(json, fooType);
336```
337
338The idiom used to get `fooType` actually defines an anonymous local inner class containing a method `getType()` that returns the fully parameterized type.
339
340### Serializing and Deserializing Collection with Objects of Arbitrary Types
341
342Sometimes you are dealing with JSON array that contains mixed types. For example:
343`['hello',5,{name:'GREETINGS',source:'guest'}]`
344
345The equivalent `Collection` containing this is:
346
347```java
348Collection collection = new ArrayList();
349collection.add("hello");
350collection.add(5);
351collection.add(new Event("GREETINGS", "guest"));
352```
353
354where the `Event` class is defined as:
355
356```java
357class Event {
358  private String name;
359  private String source;
360  private Event(String name, String source) {
361    this.name = name;
362    this.source = source;
363  }
364}
365```
366
367You can serialize the collection with Gson without doing anything specific: `toJson(collection)` would write out the desired output.
368
369However, 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
3711. 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
3732. 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
3753. Register a type adapter for `MyCollectionMemberType` and use `fromJson()` with `Collection<MyCollectionMemberType>`.
376
377This 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
379### Built-in Serializers and Deserializers
380
381Gson has built-in serializers and deserializers for commonly used classes whose default representation may be inappropriate, for instance
382
383* `java.net.URL` to match it with strings like `"https://github.com/google/gson/"`
384* `java.net.URI` to match it with strings like `"/google/gson/"`
385
386For many more, see the internal class [`TypeAdapters`](gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java).
387
388You 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
390### Custom Serialization and Deserialization
391
392Sometimes default representation is not what you want. This is often the case when dealing with library classes (DateTime, etc).
393Gson allows you to register your own custom serializers and deserializers. This is done by defining two parts:
394
395* JSON Serializers: Need to define custom serialization for an object
396* JSON Deserializers: Needed to define custom deserialization for a type
397
398* Instance Creators: Not needed if no-args constructor is available or a deserializer is registered
399
400```java
401GsonBuilder gson = new GsonBuilder();
402gson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
403gson.registerTypeAdapter(MyType.class, new MySerializer());
404gson.registerTypeAdapter(MyType.class, new MyDeserializer());
405gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
406```
407
408`registerTypeAdapter` call checks if the type adapter implements more than one of these interfaces and register it for all of them.
409
410#### Writing a Serializer
411
412Here is an example of how to write a custom serializer for JodaTime `DateTime` class.
413
414```java
415private class DateTimeSerializer implements JsonSerializer<DateTime> {
416  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
417    return new JsonPrimitive(src.toString());
418  }
419}
420```
421
422Gson calls `serialize()` when it runs into a `DateTime` object during serialization.
423
424#### Writing a Deserializer
425
426Here is an example of how to write a custom deserializer for JodaTime DateTime class.
427
428```java
429private class DateTimeDeserializer implements JsonDeserializer<DateTime> {
430  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
431      throws JsonParseException {
432    return new DateTime(json.getAsJsonPrimitive().getAsString());
433  }
434}
435```
436
437Gson calls `deserialize` when it needs to deserialize a JSON string fragment into a DateTime object
438
439**Finer points with Serializers and Deserializers**
440
441Often you want to register a single handler for all generic types corresponding to a raw type
442
443* For example, suppose you have an `Id` class for id representation/translation (i.e. an internal vs. external representation).
444* `Id<T>` type that has same serialization for all generic types
445  * Essentially write out the id value
446* Deserialization is very similar but not exactly the same
447  * Need to call `new Id(Class<T>, String)` which returns an instance of `Id<T>`
448
449Gson 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).
450The `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
452### Writing an Instance Creator
453
454While deserializing an Object, Gson needs to create a default instance of the class.
455Well-behaved classes that are meant for serialization and deserialization should have a no-argument constructor.
456
457* Doesn't matter whether public or private
458
459Typically, Instance Creators are needed when you are dealing with a library class that does NOT define a no-argument constructor
460
461**Instance Creator Example**
462
463```java
464private class MoneyInstanceCreator implements InstanceCreator<Money> {
465  public Money createInstance(Type type) {
466    return new Money("1000000", CurrencyCode.USD);
467  }
468}
469```
470
471Type could be of a corresponding generic type
472
473* Very useful to invoke constructors which need specific generic type information
474* For example, if the `Id` class stores the class for which the Id is being created
475
476#### InstanceCreator for a Parameterized Type
477
478Sometimes 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
480```java
481class MyList<T> extends ArrayList<T> {
482}
483
484class MyListInstanceCreator implements InstanceCreator<MyList<?>> {
485  @SuppressWarnings("unchecked")
486  public MyList<?> createInstance(Type type) {
487    // No need to use a parameterized list since the actual instance will have the raw type anyway.
488    return new MyList();
489  }
490}
491```
492
493However, 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
495```java
496public class Id<T> {
497  private final Class<T> classOfId;
498  private final long value;
499  public Id(Class<T> classOfId, long value) {
500    this.classOfId = classOfId;
501    this.value = value;
502  }
503}
504
505class IdInstanceCreator implements InstanceCreator<Id<?>> {
506  public Id<?> createInstance(Type type) {
507    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
508    Type idType = typeParameters[0]; // Id has only one parameterized type T
509    return new Id((Class)idType, 0L);
510  }
511}
512```
513
514In 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
516### Compact Vs. Pretty Printing for JSON Output Format
517
518The 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
520If 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
522The following is an example shows how to configure a `Gson` instance to use the default `JsonPrintFormatter` instead of the `JsonCompactFormatter`:
523
524```java
525Gson gson = new GsonBuilder().setPrettyPrinting().create();
526String jsonOutput = gson.toJson(someObject);
527```
528
529### Null Object Support
530
531The 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
533Here's how you would configure a `Gson` instance to output null:
534
535```java
536Gson gson = new GsonBuilder().serializeNulls().create();
537```
538
539NOTE: 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
541Here's an example:
542
543```java
544public class Foo {
545  private final String s;
546  private final int i;
547
548  public Foo() {
549    this(null, 5);
550  }
551
552  public Foo(String s, int i) {
553    this.s = s;
554    this.i = i;
555  }
556}
557
558Gson gson = new GsonBuilder().serializeNulls().create();
559Foo foo = new Foo();
560String json = gson.toJson(foo);
561System.out.println(json);
562
563json = gson.toJson(null);
564System.out.println(json);
565```
566
567The output is:
568
569```json
570{"s":null,"i":5}
571null
572```
573
574### Versioning Support
575
576Multiple 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
578```java
579public class VersionedClass {
580  @Since(1.1) private final String newerField;
581  @Since(1.0) private final String newField;
582  private final String field;
583
584  public VersionedClass() {
585    this.newerField = "newer";
586    this.newField = "new";
587    this.field = "old";
588  }
589}
590
591VersionedClass versionedObject = new VersionedClass();
592Gson gson = new GsonBuilder().setVersion(1.0).create();
593String jsonOutput = gson.toJson(versionedObject);
594System.out.println(jsonOutput);
595System.out.println();
596
597gson = new Gson();
598jsonOutput = gson.toJson(versionedObject);
599System.out.println(jsonOutput);
600```
601
602The output is:
603
604```json
605{"newField":"new","field":"old"}
606
607{"newerField":"newer","newField":"new","field":"old"}
608```
609
610### Excluding Fields From Serialization and Deserialization
611
612Gson 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
614#### Java Modifier Exclusion
615
616By 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
618```java
619import java.lang.reflect.Modifier;
620Gson gson = new GsonBuilder()
621    .excludeFieldsWithModifiers(Modifier.STATIC)
622    .create();
623```
624
625NOTE: you can give any number of the `Modifier` constants to the `excludeFieldsWithModifiers` method. For example:
626
627```java
628Gson gson = new GsonBuilder()
629    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
630    .create();
631```
632
633#### Gson's `@Expose`
634
635This 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
637#### User Defined Exclusion Strategies
638
639If 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
641The 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
643```java
644@Retention(RetentionPolicy.RUNTIME)
645@Target({ElementType.FIELD})
646public @interface Foo {
647  // Field tag only annotation
648}
649
650public class SampleObjectForTest {
651  @Foo private final int annotatedField;
652  private final String stringField;
653  private final long longField;
654  private final Class<?> clazzField;
655
656  public SampleObjectForTest() {
657    annotatedField = 5;
658    stringField = "someDefaultValue";
659    longField = 1234;
660  }
661}
662
663public class MyExclusionStrategy implements ExclusionStrategy {
664  private final Class<?> typeToSkip;
665
666  private MyExclusionStrategy(Class<?> typeToSkip) {
667    this.typeToSkip = typeToSkip;
668  }
669
670  public boolean shouldSkipClass(Class<?> clazz) {
671    return (clazz == typeToSkip);
672  }
673
674  public boolean shouldSkipField(FieldAttributes f) {
675    return f.getAnnotation(Foo.class) != null;
676  }
677}
678
679public static void main(String[] args) {
680  Gson gson = new GsonBuilder()
681      .setExclusionStrategies(new MyExclusionStrategy(String.class))
682      .serializeNulls()
683      .create();
684  SampleObjectForTest src = new SampleObjectForTest();
685  String json = gson.toJson(src);
686  System.out.println(json);
687}
688```
689
690The output is:
691
692```json
693{"longField":1234}
694```
695
696### JSON Field Naming Support
697
698Gson 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
700It 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
702The following is an example of how to use both Gson naming policy features:
703
704```java
705private class SomeObject {
706  @SerializedName("custom_naming") private final String someField;
707  private final String someOtherField;
708
709  public SomeObject(String a, String b) {
710    this.someField = a;
711    this.someOtherField = b;
712  }
713}
714
715SomeObject someObject = new SomeObject("first", "second");
716Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
717String jsonRepresentation = gson.toJson(someObject);
718System.out.println(jsonRepresentation);
719```
720
721The output is:
722
723```json
724{"custom_naming":"first","SomeOtherField":"second"}
725```
726
727If 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
729### Sharing State Across Custom Serializers and Deserializers
730
731Sometimes 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
7331. Store shared state in static fields
7342. Declare the serializer/deserializer as inner classes of a parent type, and use the instance fields of parent type to store shared state
7353. Use Java `ThreadLocal`
736
7371 and 2 are not thread-safe options, but 3 is.
738
739### Streaming
740
741In 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
743## Issues in Designing Gson
744
745See 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
747## Future Enhancements to Gson
748
749For 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