Gson Complete tutorial for converting Java objects to JSON-formatted objects _java

Source: Internet
Author: User
Tags compact modifier serialization static class stub tojson

Gson is a Java library that implements the conversion of JSON and Java objects to one another. Gson is an Open-source project hosted in Https://github.com/google/gson.

The main class in Gson is Gson, or you can use the class Gsonbuilder to set some options while creating Gson objects.
The Gson object does not save any state while processing JSON, so the user can easily serialize, deserialize, and so on with the same Gson object.

Example: Basic use

Serialization
Gson Gson = new Gson ();
Gson.tojson (1);   ==> Prints 1
gson.tojson ("ABCD");  ==> prints "ABCD"
Gson.tojson (New Long),//==> prints int[
] values = {1};
Gson.tojson (values);  ==> prints [1]

//deserialization
int one = Gson.fromjson ("1", int.class);
Integer one = Gson.fromjson ("1", integer.class);
Long one = Gson.fromjson ("1", long.class);
Boolean f = Gson.fromjson ("false", boolean.class);
String str = Gson.fromjson ("\" Abc\ "", String.class);
String anotherstr = Gson.fromjson ("[\" Abc\ "]", string.class);

Serialization
Bagofprimitives obj = new bagofprimitives ();
Gson Gson = new Gson ();
String json = Gson.tojson (obj); 
==> json is {"value1": 1, "value2": "ABC"}

Example: converting between objects and JSON

Define the Bagofprimitives class:

Class Bagofprimitives {
 private int value1 = 1;
 Private String value2 = "abc";
 private transient int value3 = 3;
 Bagofprimitives () {
 //No-args constructor
 }
}

Serialized as JSON:

Serialization
Bagofprimitives obj = new bagofprimitives ();
Gson Gson = new Gson ();
String json = Gson.tojson (obj); 
==> json is {"value1": 1, "value2": "ABC"}

Do not serialize an object that contains a circular reference, otherwise it can cause infinite recursion.

Deserialization:

Deserialization
bagofprimitives obj2 = Gson.fromjson (JSON, bagofprimitives.class); 
==> obj2 is just like obj

Some details when working with objects:

    • It is recommended that you use private fields (translator: You can get the names and values of private fields by reflection)
    • It is not necessary to use annotations to indicate which fields should be serialized or deserialized. All fields in the current class (also including its parent) are serialized/deserialized by default.
    • If a field is declared with a keyword transient, it is not serialized/deserialized by default.
    • Gson processing null fields as follows:
    • Null fields are skipped during serialization
    • When deserialized, a field in a class that does not have a value in the JSON setting is set to null.
    • The synthetic field is not serialized/deserialized.
    • The fields in the inner class (inner classes), anonymous classes (anonymous classes), and local classes in the outer Class (outer classes) are not serialized/deserialized.

Handling of nested classes (including internal classes)

Gson can easily serialize nested classes and enable the deserialization of static nested classes. Gson cannot automatically deserialize pure inner classes because the parameterless constructor of an inner class needs to refer to the object that contains it (that is, an instance of an external class). To deserialize a static class, you can either statically initialize the inner class or provide a custom instance creator (instance creator). Here is an example:

public Class A {public
 String A;

 Class B {public

 String B;

 Public B () {
  //No args constructor for b}}}


The above Class B cannot be serialized by Gson. Because Class B is a (non-static) inner class, Gson cannot deserialize {"B": "ABC"} into an instance of Class B. If B is declared as static Class B, then Gson can deserialize the string.

Another workaround is to write an instance builder for B:

public class Instancecreatorforb implements instancecreator<a.b> {
 private final A;
 Public Instancecreatorforb (a) {
 this.a = A;
 }
 Public a.b CreateInstance (type type) {return
 a.new B ();
 }
}

This method is feasible, but not recommended. (Translator does not understand this instance builder, do not know how to use)

Example: Arrays

Gson Gson = new Gson ();
Int[] INTs = {1, 2, 3, 4, 5};
String[] strings = {"abc", "Def", "Ghi"};

Serialization
Gson.tojson (ints);  ==> prints [1,2,3,4,5]
Gson.tojson (strings) ==> prints ["abc", "Def", "Ghi"]

//deserialization
int[] ints2 = Gson.fromjson ("[1,2,3,4,5]", int[].class);
==> Ints2 would be same as INTs

Gson also supports multidimensional arrays that have complex data types.

Example: Collection (Collection)

Gson Gson = new Gson ();
collection<integer> ints = lists.immutablelist (1,2,3,4,5);

Serialization
String JSON = Gson.tojson (ints);//==> json is [1,2,3,4,5]

//deserialization
Type CollectionType = new Typetoken<collection<integer>> () {}.gettype ();
collection<integer> ints2 = Gson.fromjson (JSON, collectiontype);
Ints2 is same as INTs

Limitations when processing collections (Collection):

    • The collection of arbitrary objects can be serialized, and deserialization is not possible.
    • When deserializing, the collection must be the specified generic.

Serialization/deserialization generics

When using Tojson (obj), Gson invokes Obj.getclass () to obtain field information for use in serialization. Similarly, object Myclass.class can be passed as arguments to the Fromjson (JSON, Myclass.class) method, which can be used when the object is not generic. However, when an object is an object of a generic type, the generic type information is lost due to the mechanism of type erasure in Java erasure. The following example will illustrate this point:

Class Foo<t> {
 T value;
}
Gson Gson = new Gson ();
foo<bar> foo = new foo<bar> ();
Gson.tojson (foo); May isn't serialize Foo.value correctly

Gson.fromjson (JSON, Foo.getclass ());//fails to deserialize Foo.value as Bar

The above code interprets value as a bar type because Gson calls Foo.getclass () to get information about the class, but that method returns an original class, that is, Foo.class. This means that Gson cannot know that this is a foo<bar> type of object.

To solve this problem, you can specify the correct parameterized type for your generics. You can use the TypeToken class to do this:

Type Footype = new typetoken<foo<bar>> () {}.gettype ();
Gson.tojson (foo, footype);
Gson.fromjson (JSON, footype);

Footype actually defines an anonymous inner class that contains a GetType () method that can return all parameterized types.

Serializing/deserializing a collection of objects containing any type

Sometimes the JSON that is processed contains a mixed type, for example:

[' Hello ', 5,{name: ' Greetings ', Source: ' Guest '}]

The corresponding set should be:

Collection Collection = new ArrayList ();
Collection.add ("Hello");
Collection.add (5);
Collection.add (New Event ("Greetings", "Guest"));

The event class is defined as follows:

Class Event {
 private String name;
 Private String source;
 Private Event (string name, string source) {
 this.name = name;
 This.source = source;
 }

By Gson, you can serialize a collection without doing anything Special: Tojson (collection) outputs a satisfying result.

However, deserialization via Fromjson (JSON, Collection.class) is not possible because Gson cannot match the content in JSON to the type. Gson requires you to provide a generic version of the collection type in Fromjson. You have three choices:

Scenario 1: Use the API of the Gson parser (low-level flow parser or DOM parser Jsonparser) to parse the array elements, and then use Gson.fromjson () to process each element. This is the preferred option.
Scenario 2: Register a type of adapter for Collection.class to map the elements in the array to the appropriate objects. The disadvantage of this approach is that it will make you inconvenience when dealing with other collection types.
Scenario 3: Register a type adapter for Mycollectionmembertype and use collection<mycollectionmembertype> in Fromjson. This is only possible if the array looks like an advanced element or if you can change the field type to Collection<mycollectionmembertype>.
Built-in serialization/deserialization

Gson provides serialization/deserialization for classes that are commonly used but that may not be appropriate by default.
Here is a list of these classes:

    • Java.net.URL, for example, is serialized as a string http://code.google.com/p/google-gson/
    • Java.net.URI, for example, is serialized as a string/p/google-gson/

Custom Serialization/deserialization

Sometimes, the default implementation of Gson is not what you want, which is more common when dealing with some class libraries, such as DateTime.

Gson allows you to register a custom serialization/deserialization device. To do this, you need to implement the following sections:

JSON serializer: You need to customize serialization for an object
JSON deserialization: You need to customize the deserialization of a type
Class Builder: If there is an parameterless constructor or if an deserialization has been registered, it is not needed.

Gsonbuilder Gson = new Gsonbuilder ();
Gson.registertypeadapter (Mytype2.class, New Mytypeadapter ());
Gson.registertypeadapter (Mytype.class, New Myserializer ());
Gson.registertypeadapter (Mytype.class, New Mydeserializer ());
Gson.registertypeadapter (Mytype.class, New Myinstancecreator ());

Registertypeadapter checks whether the type adapter implements multiple interfaces and registers the type adapters for those interfaces.

Write a serializer

The following is an example of a custom serializer for datetime:

Private class Datetimeserializer implements jsonserializer<datetime> {public
 jsonelement serialize ( DateTime src, Type typeofsrc, Jsonserializationcontext context) {return
 new jsonprimitive (src.tostring ());
 }
}

Gson calls Tojson () when serializing an instance of a DateTime.

Write an anti-serialization device

The following example is a counter serializer that tells how to write a DateTime class:

Private class Datetimedeserializer implements jsondeserializer<datetime> {public
 DateTime deserialize ( Jsonelement json, Type Typeoft, Jsondeserializationcontext context)
  throws Jsonparseexception {return
 new DateTime (Json.getasjsonprimitive (). getasstring ());
 }
}

Fromjson () is invoked when Gson needs to deserialize a JSON string into a DateTime object.

For serializers/deserialization, note:

    • In many cases, you want to register a handler that maps generics to an original type,
    • For example, if you have a class called ID to represent and convert IDs
    • Id<t> type, all generics have the same serializer, and the serializer is the value of the output ID
    • The deserialization is similar, but not exactly the same. For example, to return a Id<t> object, you need to call the new Id (CLASS<T>, String).
    • Gson supports registering a handler, you can also register the specified handler for the specified generic. The Tojson and Fromjson type parameters contain generic information to help you write a handler that maps all generics to the same original type.

Write an instance Builder

When deserializing an object, Gson needs to create an instance of the class. A class that behaves well when serializing/deserializing refers to a class that has an parameterless constructor. Typically, you need to use an instance creator when working with classes in a class library that do not have an parameterless constructor.

Instance Builder Example:

Private class Moneyinstancecreator implements instancecreator<money> {public money
 CreateInstance (type type {return
 to new money ("1000000", CURRENCYCODE.USD);
 }

Instance Builder for parameterized types

Sometimes the type to instantiate is a parameterized type. In general, since the real instance is an original type, this is not a problem. Here is an example:

Class Mylist<t> extends Arraylist<t> {
}

class Mylistinstancecreator implements Instancecreator <MyList<?>> {
 @SuppressWarnings ("unchecked") public
 mylist<?> CreateInstance (Type type {
 //No need to use a parameterized list since the actual instance'll have the raw type anyway.
 return new MyList ();
 }


However, sometimes you need to create an instance based on a real parameterized type. In this case, you can pass the type parameter to the CreateInstance method. Here is an example:

public class Id<t> {
 private final class<t> Classofid;
 Private final Long value;
 Public Id (class<t> Classofid, Long value) {
 This.classofid = Classofid;
 This.value = value;
 }
}

Class Idinstancecreator implements instancecreator<id<?>> {public
 id<?> CreateInstance (Type Type) {
 type[] typeparameters = ((parameterizedtype) type). Getactualtypearguments ();
 Type idtype = typeparameters[0]; Id has only one parameterized type T return
 id.get ((Class) Idtype, 0L);
 }


In the example above, an instance of an ID class cannot be created without passing the true type to the parameterized type. We can solve this problem by passing the parameter type to the method. Here, the type object can be seen as a representation of the id<foo> Java parameterized type, and the corresponding instance should be bound to id<foo>. Since the class ID has only one parameterized type of parameter T, we use the No. 0 element of the type array returned by Getactualtypeargument (), in this case the Foo.class.

Compact output VS. Graceful output

The default output of JSON in Gson is the compact JSON format. That is, there are no extra whitespace characters in the JSON. So there is no white space between field names and field values, between fields, and between array elements in the output of JSON. In addition, NULL fields are not exported (note: null is preserved in collections and array objects).

If you want to export more gracefully, you need to use Gsonbuilder to configure the Gson instance. Jsonformatter does not exist in the public API, so clients cannot configure the default output settings. Now we only provide the Jsonprintformatter, which by default is 80 characters per line, indents with 2 characters, and the right margin is 4 characters.

The following example shows how to let a Gson instance use Jsonprintformatter instead of using the default Jsoncompactformatter.

Gson Gson = new Gsonbuilder (). setprettyprinting (). Create ();
String jsonoutput = Gson.tojson (someobject);

Empty Object

In the default implementation of Gson, the null object is ignored. This allows the output format to be tighter than the result that can be serialized, although the client must define a default value for it to enable JSON to deserialize properly.

If you want to allow the Gson instance to serialize NULL, you can:

Gson Gson = new Gsonbuilder (). Serializenulls (). Create ();

Note that when you serialize null, a JSONNULL element is added to the jsonelement structure. Therefore, we can use this object (Gson) in a custom serializer/deserialization.

Here is an example:

public class Foo {
 private final String s;
 private final int i;

 Public Foo () {This
 (null, 5);
 }

 Public Foo (String s, int i) {
 THIS.S = s;
 THIS.I = i
 }
}

Gson Gson = new Gsonbuilder (). Serializenulls (). Create ();
Foo foo = new Foo ();
String json = Gson.tojson (foo);
SYSTEM.OUT.PRINTLN (JSON);

JSON = Gson.tojson (null);
SYSTEM.OUT.PRINTLN (JSON);

Output:

{"S": null, "I": 5}
Null

Version support

You can use the @since annotation to maintain multiple versions of the same object. This annotation can be used on classes and fields and will also be supported on methods in the future. To use this feature, you need to configure the Gson instance to ignore fields and objects larger than a certain version number. If the version is not set in the Gson object, all fields and classes are used for serialization/deserialization.

public class Versionedclass {
 @Since (1.1) Private final String Newerfield;
 @Since (1.0) Private final String Newfield;
 Private final String field;

 Public Versionedclass () {
 This.newerfield = "newer";
 This.newfield = "new";
 This.field = "old";
 }

Versionedclass versionedobject = new Versionedclass ();
Gson Gson = new Gsonbuilder (). Setversion (1.0). Create ();
String jsonoutput = Gson.tojson (someobject);
System.out.println (jsonoutput);
System.out.println ();

Gson = new Gson ();
Jsonoutput = Gson.tojson (someobject);
System.out.println (Jsonoutput);

Output:

{"Newfield": "New", "field": "Old"}

{"Newerfield": "Newer", "Newfield": "New", "field": "Old"}

Excluding fields from serialization/deserialization

Gson supports the use of many methods to remove classes, fields, and field types. If the following methods do not meet your needs, you can use the method of customizing serialization/deserialization.

1.Java Modifier Exclusion

By default, this field is excluded if a field is declared as transient. In addition, if a field is declared static, the field is also excluded by default. If you want to include certain fields that are declared as transient, you can do this:

Import Java.lang.reflect.Modifier;

Gson Gson = new Gsonbuilder ()
 . Excludefieldswithmodifiers (modifier.static)
 . Create ();

Note that in the Excludefieldswithmodifiers method, you can use any number of modifier constants. For example:

Gson Gson = new Gsonbuilder ()
 . Excludefieldswithmodifiers (Modifier.static, Modifier.transient, Modifier.VOLATILE )
 . Create ();

2. Using the @expose field to exclude

This feature allows you to mark specific fields in a class so that they are not excluded/excluded in serialization/deserialization. To use this annotation, you should create a Gson using the new Gsonbuilder (). Excludefieldswithoutexposeannotation (). The Gson instance excludes all fields that are not @expose annotated in the class.

3. User-defined exclusion policy

If the above exclusion method does not meet the requirements, you can also customize your own exclusion strategy. For more information, you can refer to Exclusionstrategy JavaDoc.

The following example shows how to exclude a field that uses the @foo annotation, excluding the top-level type of the string class or the declared field type:

 

@Retention (Retentionpolicy.runtime) @Target ({Elementtype.field}) public @interface Foo {//FIELD tag only annotation
 public class Sampleobjectfortest {@Foo private final int annotatedfield;
 Private final String Stringfield;
 Private final long Longfield;

 Private final class<?> Clazzfield;
  Public Sampleobjectfortest () {Annotatedfield = 5;
  Stringfield = "Somedefaultvalue";
 Longfield = 1234;

 } public class Myexclusionstrategy implements Exclusionstrategy {private final class<?> typetoskip;
 Private Myexclusionstrategy (class<?> typetoskip) {this.typetoskip = Typetoskip;
 public boolean shouldskipclass (class<?> clazz) {return (Clazz = = Typetoskip);
 public boolean Shouldskipfield (FieldAttributes f) {return f.getannotation (foo.class)!= null; } public static void Main (string[] args) {Gson Gson = new Gsonbuilder (). Setexclusionstrategies (New Myexclusionst
 Rategy (String.class)). Serializenulls (). Create (); Sampleobjectfortest src = new sampleobjectfortest ();
 String json = Gson.tojson (SRC);
 SYSTEM.OUT.PRINTLN (JSON);

 }

Output:

{"Longfield": 1234}

JSON field naming support

Gson's predefined field naming policies allow you to convert a standard Java field name (that is, the hump naming method, such as Samplefieldnameinjava) to a JSON field name (that is, sample_field_name_in_ Java or Samplefieldnameinjava). For more information, refer to Fieldnamingpolicy.

Gson also has a callout based policy that allows the client to customize the name of the field. Under this policy, if an illegal field name is provided as the value of the callout, the Gson throws a runtime exception.

The following example shows how to use both of these Gson naming policies:

Private class Someobject {
 @SerializedName ("custom_naming") private final String Somefield;
 Private final String Someotherfield;

 Public Someobject (String A, string b) {
 This.somefield = A;
 This.someotherfield = b;
 }
}

Someobject someobject = new Someobject ("A", "second");
Gson Gson = new Gsonbuilder (). Setfieldnamingpolicy (Fieldnamingpolicy.upper_camel_case). Create ();
String jsonrepresentation = Gson.tojson (someobject);
System.out.println (jsonrepresentation);

Output:

{"custom_naming": "I", "Someotherfield": "Second"}

If you want to customize the name, you can use the @serializedname callout.

Sharing a state between a serializer and a deserialization device

Sometimes you will need to share the state between the serializer and the deserialization, and you can use the following three methods to achieve the goal:

    • Store shared state in a static field
    • Declare the serialization/deserialization as an inner class of a parent type, and then use the fields of the instance of the parent type to store the shared state
    • Using the threadlocal in Java

The first two methods are not thread safe, and the third is.


Gson resolve NULL Error Resolution
One drawback of Gson is that null substitution cannot be set.
We can only manually replace the server returned null, the normal interface definition is absolutely not allow the server to return null, background results will always appear null!
If there's a common answer to the search,

Gson Gson = new Gsonbuilder (). Serializenulls (). Create ();

But this does not solve the inverse sequence problem, how to solve it?
The solution is as follows:

Gson Gson = new Gsonbuilder (). Registertypeadapterfactory (New Nullstringtoemptyadapterfactory ()). Create ();
The Entity class type Gson.fromjson (JSON, type) is then serialized and deserialized with the Gson written in the line above.
Gson.tojson (type); Nullstringtoemptyadapterfactory code public class Nullstringtoemptyadapterfactory<t> implements typeadapterfactory {@SuppressWarnings ("unchecked") public <T> typeadapter<t> Create (Gson Gson, typetoken& Lt
  T> type) {class<t> Rawtype = (class<t>) type.getrawtype ();
  if (Rawtype!= string.class) {return null;
 Return (typeadapter<t>) new Stringnulladapter (); }//Stringnulladapter code public class Stringnulladapter extends typeadapter<string> {@Override public String R
   EAD (Jsonreader reader) throws IOException {//TODO auto-generated Method stub if (reader.peek () = = Jsontoken.null) {
   Reader.nextnull ();
  Return "";
 return reader.nextstring ();
@Override public void Write (Jsonwriter writer, String value) throws IOException {  TODO auto-generated Method Stub if (value = = null) {Writer.nullvalue ();
  Return
 } writer.value (value);
 }
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.