- 전체
- JAVA 일반
- JAVA 수학
- JAVA 그래픽
- JAVA 자료구조
- JAVA 인공지능
- JAVA 인터넷
- Java Framework
- Java GUI (AWT,SWING,SWT,JFACE)
- SWT and RCP (web RAP/RWT)[eclipse], EMF
JAVA 자료구조 GSON Serialiser Example [Java class의 JSON 변환]
2015.10.21 21:48
GSON Serialiser Example [Java class의 JSON 변환]
GSON Serialiser Example
Java objects can be converted into JSON strings using the Gson API (Homepage). In this article we will see how we can convert Java objects into JSON strings using both the default Gson implementation and custom implementation.
The readers of this article are encouraged to read the articles: Simple Gson Example and Gson Deserialiser Example, if they are not familiar with Gson. Furthermore, this article is structured in the same way as the article Gson Deserialiser Example and the same examples are used here.
Observation
Please note the we will use the terms format or serialise interchangeably in this article.
All code listed below is available at: http://java-creed-examples.googlecode.com/svn/gson/Gson Serialiser Example/. Most of the examples will not contain the whole code and may omit fragments which are not relevant to the example being discussed. The readers can download or view all code from the above link.
Simple Example
Consider the following Java object.
package com.javacreed.examples.gson.part1;
public class Book {
private String[] authors;
private String isbn10;
private String isbn13;
private String title;
// Methods removed for brevity
}
This is a simple Java class representing a book. Say that we need to serialise this class into the following JSON object.
{ "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases", "isbn-10": "032133678X", "isbn-13": "978-0321336781", "authors": [ "Joshua Bloch", "Neal Gafter" ] }
Gson can seriliase the Book
class without any special configuration, just using the default configuration. Gson uses the Java field names as the JSON names and will serialise their values accordingly. If we take a closer look to the JSON sample shown above, we will see that the ISBN fields contain a minus sign: isbn-10
and isbn-13
. Unfortunately, we cannot obtain these field names using teh default Gson configuration. One way to address this problem is to use annotations as described in the article: Gson Annotations Example. Using annotations we can define the JSON field names and Gson will take case of the rest. Another approach is to use a JsonSerialiser
(Java Doc) as shown in the following example.
package com.javacreed.examples.gson.part1; import java.lang.reflect.Type; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class BookSerialiser implements JsonSerializer{ @Override public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); //The serialisation code is missing return jsonObject; } }
The above example is not complete and we still need to add the most important thing, which is the serialisation. Let’s understand this class before we make it more complex by adding more code to it.
The interface JsonSerializer
requires a type, which is the type of object that we will be serialised. In this case, we are serialising the Java object of type Book
into JSON object. The return type of the serialize()
method must be an instance of type JsonElement
(Java Doc). As described in more detail in the article: Gson Deserialiser Example, the JsonElement
has four concrete types listed below:
JsonPrimitive
(Java Doc) – such as a string or integerJsonObject
(Java Doc) – a collection ofJsonElement
s indexed by thier name (of typeString
). This is similar to aMap<String, JsonElement>
(Java Doc)JsonArray
(Java Doc) – a collection ofJsonElement
s. Note that the array elements can be any of the four types and mixed types are supported.JsonNull
(Java Doc) – anull
value
The above image shows all types of JsonElement
. The JsonObject
can be thought of a collection of name/value pairs where the values are of type JsonElement
. Therefore, the values can yet be other objects.
Following is a complete example of our serialiser.
package com.javacreed.examples.gson.part1; import java.lang.reflect.Type; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class BookSerialiser implements JsonSerializer{ @Override public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("title", book.getTitle()); jsonObject.addProperty("isbn-10", book.getIsbn10()); jsonObject.addProperty("isbn-13", book.getIsbn13()); final JsonArray jsonAuthorsArray = new JsonArray(); for (final String author : book.getAuthors()) { final JsonPrimitive jsonAuthor = new JsonPrimitive(author); jsonAuthorsArray.add(jsonAuthor); } jsonObject.add("authors", jsonAuthorsArray); return jsonObject; } }
We added some code here. Let us break this into smaller parts and understand each individual part before understanding the whole picture.
If we are to serialise this Java object, we first need to create the correct instance of the JsonElement
. In our example we are returning an instance of JsonObject
as our Book
is an object as shown next.
final JsonObject jsonObject = new JsonObject();
This object will be populated with our fields using the names we like as shown next
// The variable 'book' is passed as a parameter to the serialize() method final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("title", book.getTitle()); jsonObject.addProperty("isbn-10", book.getIsbn10()); jsonObject.addProperty("isbn-13", book.getIsbn13());
Using the addProperty()
(Java Doc) method we can add any Java primitive together with String
s and Number
s. Note that the property name must be unique, otherwise it will replace the previous value. This can be thought of a Map
(Java Doc) holding all values index by their name.
More complex objects such as Java objects and arrays cannot be added using the method shown above. The JsonObject
has another method called add()
(Java Doc), which can be used instead as shown below.
// The variable 'book' is passed as a parameter to the serialize() method jsonObject.addProperty("title", book.getTitle()); jsonObject.addProperty("isbn-10", book.getIsbn10()); jsonObject.addProperty("isbn-13", book.getIsbn13()); final JsonArray jsonAuthorsArray = new JsonArray(); for (final String author : book.getAuthors()) { final JsonPrimitive jsonAuthor = new JsonPrimitive(author); jsonAuthorsArray.add(jsonAuthor); } jsonObject.add("authors", jsonAuthorsArray);
We first create the JsonArray
and added all authors to it. Different from Java, we do not need to define the size of the array when initialising it. In fact, despite its name, we can think of the JsonArray
class more as a list rather than array. Finally the variable jsonAuthorsArray
is added to the json object. Note that we can add the jsonAuthorsArray
to the jsonObject
before adding its elements.
Before we can use our serialiser, we need to register it with Gson as shown below.
package com.javacreed.examples.gson.part1; import java.io.IOException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Main { public static void main(final String[] args) throws IOException { // Configure GSON final GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser()); gsonBuilder.setPrettyPrinting(); final Gson gson = gsonBuilder.create(); final Book javaPuzzlers = new Book(); javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases"); javaPuzzlers.setIsbn10("032133678X"); javaPuzzlers.setIsbn13("978-0321336781"); javaPuzzlers.setAuthors(new String[] { "Joshua Bloch", "Neal Gafter" }); // Format to JSON final String json = gson.toJson(javaPuzzlers); System.out.println(json); } }
By registering our serialiser, we are instructing Gson to using this serialiser whenever an object of type Book
is serialised.
In the example shown above, we also instructed Gson to format the JSON object, by invoking the set pretty printing shown next.
gsonBuilder.setPrettyPrinting();
While this is useful for tutorials and debugging, please avoid this in production environment as this may produce larger JSON objects (in terms of text size) due to the formatting. Furthermore, pretty printing has a slight performance cost as Gson has to format the JSON objects and indent these accordingly.
Running the above code will produce the desired JSON object. This concludes our first example of how to use a custom Gson serialiser to serialise Java objects into JSON objects. In the following section we will se how to serialise nested objects using Gson.
Nested Objects
In this example we will describe how to serialise nested objects, that is, objects within other objects. Here we will introduce a new entity, the author. A book, together with the title and ISBN can have a list of authors. The JSON object that will be produced in this example differs from the previous one to cater for the new entity as shown next:
{
"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
"isbn": "032133678X",
"authors": [
{
"id": 1,
"name": "Joshua Bloch"
},
{
"id": 2,
"name": "Neal Gafter"
}
]
}
Note that in the previous example the authors were simply an array of strings as shown next:
"authors": [ "Joshua Bloch", "Neal Gafter" ]
In this example, the authors are JSON objects, not just primitives as shown next.
{ "id": 1, "name": "Joshua Bloch" }
The JSON author has an id and a name. Following is an example of the Author
class.
package com.javacreed.examples.gson.part2;
public class Author {
private int id;
private String name;
// Methods removed for brevity
}
This class is very straightforward. It comprise two fields, both JsonPrimitive
s. The Book
class was modified to make use of the Author
, as shown below.
package com.javacreed.examples.gson.part2; public class Book { private Author[] authors; private String isbn; private String title; // Methods removed for brevity }
The authors field was changed from an array of integers to an array of Author
s. The BookSerialiser
class has to be modified too in order to accommodate this change, as shown below.
package com.javacreed.examples.gson.part2;
import java.lang.reflect.Type;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class BookSerialiser implements JsonSerializer<Book> {
@Override
public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", book.getTitle());
jsonObject.addProperty("isbn", book.getIsbn());
final JsonElement jsonAuthros = context.serialize(book.getAuthors());
jsonObject.add("authors", jsonAuthros);
return jsonObject;
}
}
The serialisation of the authors is delegated to the context (an instance of JsonSerializationContext
(Java Doc) passed as a parameter to the serialize()
method). The context will serialise the given objects and return a JsonElement
. In turn the context will try to locate a serialiser that can serialise the given object and if none are found, it uses the default mechanism. For the time being we will not write a serialiser for the Author
class, but instead we will use the default one.
package com.javacreed.examples.gson.part2;
import java.io.IOException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class Main {
public static void main(final String[] args) throws IOException {
// Configure GSON
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser());
gsonBuilder.setPrettyPrinting();
final Gson gson = gsonBuilder.create();
final Author joshuaBloch = new Author();
joshuaBloch.setId(1);
joshuaBloch.setName("Joshua Bloch");
final Author nealGafter = new Author();
nealGafter.setId(2);
nealGafter.setName("Neal Gafter");
final Book javaPuzzlers = new Book();
javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases");
javaPuzzlers.setIsbn("032133678X");
javaPuzzlers.setAuthors(new Author[] { joshuaBloch, nealGafter });
final String json = gson.toJson(javaPuzzlers);
System.out.println(json);
}
}
The above example, creates and configures Gson to use our BookSerialiser
. We created two authors and a book and serialised the book. This will produce the JSON object shown at the beginning of this section.
For completeness we will also include a serialiser for the Author
class as shown below.
package com.javacreed.examples.gson.part2; import java.lang.reflect.Type; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class AuthorSerialiser implements JsonSerializer<Author> { @Override public JsonElement serialize(final Author author, final Type typeOfSrc, final JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", author.getId()); jsonObject.addProperty("name", author.getName()); return jsonObject; } }
The above serialiser introduces no new features and thus requires no explanation. In order to use this new serialiser we need to register it with the GsonBuilder
(Java Doc).
This concludes the section about nested objects. Using the context, we can delegate the serialisation of nested objects to the context which will in turn locate the proper serialiser and produce the respective JsonElement
. In the next and final section we will see how to deal with object references.
Object References
Objects refer to other objects and the books and authors classes are no exception. The same author can have many books. For example author Joshua Bloch (Author at Amazon), has several books. Using the serialiser described before, we will end up in duplicate authors.
Consider the following example:
package com.javacreed.examples.gson.part3; import java.io.IOException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Example1 { public static void main(final String[] args) throws IOException { // Configure GSON final GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setPrettyPrinting(); final Gson gson = gsonBuilder.create(); final Author joshuaBloch = new Author(); joshuaBloch.setId(1); joshuaBloch.setName("Joshua Bloch"); final Author nealGafter = new Author(); nealGafter.setId(2); nealGafter.setName("Neal Gafter"); final Book javaPuzzlers = new Book(); javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases"); javaPuzzlers.setIsbn("032133678X"); javaPuzzlers.setAuthors(new Author[] { joshuaBloch, nealGafter }); final Book effectiveJava = new Book(); effectiveJava.setTitle("Effective Java (2nd Edition)"); effectiveJava.setIsbn("0321356683"); effectiveJava.setAuthors(new Author[] { joshuaBloch }); final Book[] books = new Book[] { javaPuzzlers, effectiveJava }; final String json = gson.toJson(books); System.out.println(json); } }
Here we have two authors and two books. One of the author is shared between two books. Note that we have two author objects not three, as the instance representing Joshua Bloch is shared between both books. Finally note that we are not using any custom serialisers on purpose. The following is produced when executing the above code.
[ { "authors": [ { "id": 1, "name": "Joshua Bloch" }, { "id": 2, "name": "Neal Gafter" } ], "isbn": "032133678X", "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases" }, { "authors": [ { "id": 1, "name": "Joshua Bloch" } ], "isbn": "0321356683", "title": "Effective Java (2nd Edition)" } ]
We have two JSON books and three JSON authors. The author: Joshua Bloch, shown below, is duplicated.
{ "id": 1, "name": "Joshua Bloch" }
This increases the size of the JSON object considerable, especially with more complex objects. Ideally, the book JSON object only contains the authors’ ids rather than the whole object. This resembles relational databases (Wiki) where the book has a foreign key (Wiki) to the authors table.
The Book
class is modified to include a method that return just the authors’ ids as shown below.
package com.javacreed.examples.gson.part3; public class Book { private Author[] authors; private String isbn; private String title; public Author[] getAuthors() { return authors; } public int[] getAuthorsIds() { final int[] ids = new int[authors.length]; for (int i = 0; i < ids.length; i++) { ids[i] = authors[i].getId(); } return ids; } // Other methods removed for brevity }
When serialising the books we will use the authors’ id instead of the authors as shown next.
package com.javacreed.examples.gson.part3; import java.lang.reflect.Type; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class BookSerialiser implements JsonSerializer{ @Override public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) { final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("title", book.getTitle()); jsonObject.addProperty("isbn", book.getIsbn()); final JsonElement jsonAuthros = context.serialize(book.getAuthorsIds()); jsonObject.add("authors", jsonAuthros); return jsonObject; } }
Using this serialiser we will obtain the following:
[ { "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases", "isbn": "032133678X", "authors": [ 1, 2 ] }, { "title": "Effective Java (2nd Edition)", "isbn": "0321356683", "authors": [ 1 ] } ]
Now instead of the whole author object we have just the author’s ids. This approach requires less space than the previous one where the whole author is serialised. This will have a huge effect on larger object graphs.
This example concludes this article about serialisation. Here we saw how we can serialise Java objects into JSON strings using default and custom serialisation options.
[출처] http://www.javacreed.com/gson-serialiser-example/
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.