Welcome to Gson Example Tutorial. In last post we looked at the Java JSON API and you can easily tell that it’s not convenient to use it. Whether you have to convert JSON to Java Object or otherwise, you need to write a lot of code that is tightly coupled with the JSON structure.
Gson
I started looking out for some other JSON parser API that can do the transformation itself and found about Google Gson. Gson is an open source code and it’s used a lot in working with JSON and Java. Gson uses Java Reflection to provide simple methods to convert JSON to java and vice versa.
Gson Maven
You can download Gson jar file from google code website or if you are using maven then all you need is to add it’s dependency like below.
<dependencies>
<!-- Gson dependency -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
Gson is very powerful API and it supports Java Generics. Gson API also supports out of the box JSON to Java Object conversion if the object field names are same as in json. If we want to use different name for java bean and json, then we can use @SerializedName java annotation and map the variables in JSON and Java Class.
Gson Example
Let’s look at a complex Gson example that involves nested object and array in JSON and we will map it to java bean properties of type List, Map, Array etc.
employee.txt
{
"empID": 100,
"name": "David",
"permanent": false,
"address": {
"street": "BTM 1st Stage",
"city": "Bangalore",
"zipcode": 560100
},
"phoneNumbers": [
123456,
987654
],
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
],
"properties": {
"age": "28 years",
"salary": "1000 Rs"
}
}
Let’s create the java bean classes to convert JSON to Java Object.
Employee.java
package com.journaldev.json.model;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.google.gson.annotations.SerializedName;
public class Employee {
@SerializedName("empID")
private int id;
private String name;
private boolean permanent;
private Address address;
private long[] phoneNumbers;
private String role;
private List<String> cities;
private Map<String, String> properties;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isPermanent() {
return permanent;
}
public void setPermanent(boolean permanent) {
this.permanent = permanent;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long[] getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(long[] phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("***** Employee Details *****n");
sb.append("ID="+getId()+"n");
sb.append("Name="+getName()+"n");
sb.append("Permanent="+isPermanent()+"n");
sb.append("Role="+getRole()+"n");
sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"n");
sb.append("Address="+getAddress()+"n");
sb.append("Cities="+Arrays.toString(getCities().toArray())+"n");
sb.append("Properties="+getProperties()+"n");
sb.append("*****************************");
return sb.toString();
}
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}
Address.java
package com.journaldev.json.model;
public class Address {
private String street;
private String city;
private int zipcode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
@Override
public String toString(){
return getStreet() + ", "+getCity()+", "+getZipcode();
}
}
Here is the java program showing Gson example to parse JSON.
EmployeeGsonExample.java
package com.journaldev.json.gson;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.journaldev.json.model.Address;
import com.journaldev.json.model.Employee;
public class EmployeeGsonExample {
public static void main(String[] args) throws IOException {
Employee emp = createEmployee();
// Get Gson object
Gson gson = new GsonBuilder().setPrettyPrinting().create();
// read JSON file data as String
String fileData = new String(Files.readAllBytes(Paths
.get("employee.txt")));
// parse json string to object
Employee emp1 = gson.fromJson(fileData, Employee.class);
// print object data
System.out.println("nnEmployee Objectnn" + emp1);
// create JSON String from Object
String jsonEmp = gson.toJson(emp);
System.out.print(jsonEmp);
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List<String> cities = new ArrayList<String>();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map<String, String> props = new HashMap<String, String>();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
return emp;
}
}
Gson is the main class that exposes the methods fromJson()
and toJson()
for conversion. For default implementation, we can create this object directly or we can use GsonBuilder class that provide useful options for conversion such as pretty printing, field naming convention, excluding fields, date format etc.
When you will run above gson example program, we will get following output for java object.
Employee Object
***** Employee Details *****
ID=100
Name=David
Permanent=false
Role=Manager
Phone Numbers=[123456, 987654]
Address=BTM 1st Stage, Bangalore, 560100
Cities=[Los Angeles, New York]
Properties={age=28 years, salary=1000 Rs}
*****************************
You can see how easy it is to use Gson and that’s why Gson is a very popular java API for JSON parsing.
The above Gson example of JSON parsing is known as Object model because whole JSON is converted to object at once. Most of the times it’s enough for us but if JSON is really huge and we don’t want to have all of it in memory at once, Gson provides Streaming API too.
Gson Example Parse JSON using Streaming API
Let’s see Gson example where we will use Streaming API for json to java object conversion.
EmployeeGsonReader.java
package com.journaldev.json.gson;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.journaldev.json.model.Address;
import com.journaldev.json.model.Employee;
public class EmployeeGsonReader {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("employee.txt");
InputStreamReader isr = new InputStreamReader(is);
//create JsonReader object
JsonReader reader = new JsonReader(isr);
//create objects
Employee emp = new Employee();
Address add = new Address();
emp.setAddress(add);
List<Long> phoneNums = new ArrayList<Long>();
emp.setCities(new ArrayList<String>());
emp.setProperties(new HashMap<String, String>());
String key = null;
boolean insidePropertiesObj=false;
key = parseJSON(reader, emp, phoneNums, key, insidePropertiesObj);
long[] nums = new long[phoneNums.size()];
int index = 0;
for(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
reader.close();
//print employee object
System.out.println("Employee Objectnn"+emp);
}
private static String parseJSON(JsonReader reader, Employee emp,
List<Long> phoneNums, String key, boolean insidePropertiesObj) throws IOException {
//loop to read all tokens
while(reader.hasNext()){
//get next token
JsonToken token = reader.peek();
switch(token){
case BEGIN_OBJECT:
reader.beginObject();
if("address".equals(key) || "properties".equals(key)){
while(reader.hasNext()){
parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
}
reader.endObject();
}
break;
case END_OBJECT:
reader.endObject();
if(insidePropertiesObj) insidePropertiesObj=false;
break;
case BEGIN_ARRAY:
reader.beginArray();
if("phoneNumbers".equals(key) || "cities".equals(key)){
while(reader.hasNext()){
parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
}
reader.endArray();
}
break;
case END_ARRAY:
reader.endArray();
break;
case NAME:
key = reader.nextName();
if("properties".equals(key)) insidePropertiesObj=true;
break;
case BOOLEAN:
if("permanent".equals(key)) emp.setPermanent(reader.nextBoolean());
else{
System.out.println("Unknown item found with key="+key);
//skip value to ignore it
reader.skipValue();
}
break;
case NUMBER:
if("empID".equals(key)) emp.setId(reader.nextInt());
else if("phoneNumbers".equals(key)) phoneNums.add(reader.nextLong());
else if("zipcode".equals(key)) emp.getAddress().setZipcode(reader.nextInt());
else {
System.out.println("Unknown item found with key="+key);
//skip value to ignore it
reader.skipValue();
}
break;
case STRING:
setStringValues(emp, key, reader.nextString(), insidePropertiesObj);
break;
case NULL:
System.out.println("Null value for key"+key);
reader.nextNull();
break;
case END_DOCUMENT:
System.out.println("End of Document Reached");
break;
default:
System.out.println("This part will never execute");
break;
}
}
return key;
}
private static void setStringValues(Employee emp, String key,
String value, boolean insidePropertiesObj) {
if("name".equals(key)) emp.setName(value);
else if("role".equals(key)) emp.setRole(value);
else if("cities".equals(key)) emp.getCities().add(value);
else if ("street".equals(key)) emp.getAddress().setStreet(value);
else if("city".equals(key)) emp.getAddress().setCity(value);
else{
//add to emp properties map
if(insidePropertiesObj){
emp.getProperties().put(key, value);
}else{
System.out.println("Unknown data found with key="+key+" value="+value);
}
}
}
}
Since JSON is a recursive language, we need to call our parsing method recursively for array and nested object. JsonToken is java enum returned by JsonReader next()
method that we can use with conditional logic or switch case statements for conversion.
From the code above, you can understand that it’s not an easy implementation and if the JSON is really complex, then this code will become very hard to maintain. Avoid using it until unless there is no way to use Object based model.
Gson Example to Write Object to File
Let’s see how we can write Employee object using Gson Streaming API.
EmployeeGsonWriter.java
package com.journaldev.json.gson;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Set;
import com.google.gson.stream.JsonWriter;
import com.journaldev.json.model.Employee;
public class EmployeeGsonWriter {
public static void main(String[] args) throws IOException {
Employee emp = EmployeeGsonExample.createEmployee();
//writing on console, we can initialize with FileOutputStream to write to file
OutputStreamWriter out = new OutputStreamWriter(System.out);
JsonWriter writer = new JsonWriter(out);
//set indentation for pretty print
writer.setIndent("t");
//start writing
writer.beginObject(); //{
writer.name("id").value(emp.getId()); // "id": 123
writer.name("name").value(emp.getName()); // "name": "David"
writer.name("permanent").value(emp.isPermanent()); // "permanent": false
writer.name("address").beginObject(); // "address": {
writer.name("street").value(emp.getAddress().getStreet()); // "street": "BTM 1st Stage"
writer.name("city").value(emp.getAddress().getCity()); // "city": "Bangalore"
writer.name("zipcode").value(emp.getAddress().getZipcode()); // "zipcode": 560100
writer.endObject(); // }
writer.name("phoneNumbers").beginArray(); // "phoneNumbers": [
for(long num : emp.getPhoneNumbers()) writer.value(num); //123456,987654
writer.endArray(); // ]
writer.name("role").value(emp.getRole()); // "role": "Manager"
writer.name("cities").beginArray(); // "cities": [
for(String c : emp.getCities()) writer.value(c); //"Los Angeles","New York"
writer.endArray(); // ]
writer.name("properties").beginObject(); //"properties": {
Set<String> keySet = emp.getProperties().keySet();
for(String key : keySet) writer.name("key").value(emp.getProperties().get(key));//"age": "28 years","salary": "1000 Rs"
writer.endObject(); // }
writer.endObject(); // }
writer.flush();
//close writer
writer.close();
}
}
Converting java object to JSON is comparatively easy than parsing with Gson streaming API. By default JsonWriter writes json in compact form but we can set indent for pretty printing.
That’s all for Gson example tutorial, let me know if you face any issues with it. Download project from below link and play around with different options Gson provides.
References: