Convert Java Object (POJO) To and From JSON with Gson

Introduction

The JSON format is one of the most popular ways to serialize data. Knowing how to read and write it is an important skill for any programmer. There are a couple of Java libraries that can parse JSON, but in this tutorial, we'll focus on an open-source project developed by Google called GSON.

GSON is a lightweight Java library that provides serialization/deserialization functionality. What makes GSON stand apart is its support for Generic Types, which is limited with some, but not all, alternative libraries.

Note: If you're not familiar with Generics and why this is a big deal - feel free to read our Guide to Understanding Java Generics.

Since we're working with an external library, let's add the dependency. If you're using Maven, you can add it with:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>${version}</version>
</dependency>

Or if you're using Gradle, you can add:

compile group: 'com.google.code.gson', name: 'gson', version: ${version}

Creating a Custom Class

Let's create a custom class that we'll first serialize into JSON, and into which we'll deserialize from JSON - Student:

public class Student {
    private String firstName;
    private String lastName;
    private int studentID;
    private String email;
    private List<String> courses;
    private FINANCE_TYPE financeType;

     // Getters, setters, constructor, toString()
}

For our Student, we additionally have an enum representing whether they're on the budget (SUBSIDIZED) or not (UNSUBSIDIZED):

public enum FINANCE_TYPE {
    SUBSIDIZED, UNSUBSIDIZED
}

Convert Java Object to JSON Object with GSON

Now that we have defined our class, let's make an instance of it and serialize it into its equivalent JSON representation. We will do this by using the method called toJson() that takes an object as an argument and returns the JSON representation of that object:

// Defining courses
List<String> physicsCourses = Arrays.asList("Physics 8.01", "Physics 8.012");
List<String> musicCourses = Arrays.asList("Jazz", "Blues");
 
// Instantiating students
Student max = new Student("Max", "Tegmark", 1254, "[email protected]", physicsCourses, FINANCE_TYPE.SUBSIDIZED);
Student amy = new Student("Amy", "Winehouse", 1328, "[email protected]", musicCourses, FINANCE_TYPE.SUBSIDIZED);

// Instantiating Gson
Gson gson = new Gson();

// Converting POJO to JSON
String maxJson = gson.toJson(max);
String amyJson = gson.toJson(amy);

System.out.println(maxJson);
System.out.println(amyJson);

This converts our POJOs to JSON Strings, which when printed result in:

{"firstName":"Max","lastName":"Tegmark","studentID":1254,"email":"[email protected]","courses":["Physics 8.01","Physics 8.012"],"financeType":"SUBSIDIZED"}
{"firstName":"Amy","lastName":"Winehouse","studentID":1328,"email":"[email protected]","courses":["Jazz","Blues"],"financeType":"SUBSIDIZED"}

Convert JSON String to Java Object

To reverse this process, and to map a JSON object to a POJO, we'll utilize the fromJson() method. It accepts a JSON String or a Reader and a class or a TypeToken.

Let's first take a look at the former:

String maxJson = "{\"firstName\":\"Max\",\"lastName\":\"Tegmark\",\"studentID\":1254,\"email\":\"[email protected]\",\"courses\":[\"Physics 8.01\",\"Physics 8.012\"],\"financeType\":\"SUBSIDIZED\"}";

Gson gson = new Gson();
Student max = gson.fromJson(maxJson, Student.class);

System.out.println(max);

This instantiates and populated the max object with the data from the JSON object:

Student{firstName='Max', lastName='Tegmark', studentID=1254, email='[email protected]', courses=[Physics 8.01, Physics 8.012], financeType=SUBSIDIZED}

Convert JSON File to Java Object

Now, we might not be working with JSON in String format - we oftentimes have to read JSON files. The fromJson() method accepts a Reader instance, which we can also use to provide JSON data.

Let's move Amy's data into an amy.json file:

{
  "firstName":"Amy",
  "lastName":"Winehouse",
  "studentID":1328,
  "email":"[email protected]",
  "courses":[
    "Jazz",
    "Blues"
  ],
  "financeType":"SUBSIDIZED"
}

Now, we can use a Reader, such as FileReader to read this file and use that for the input instead of a String. Additionally, instead of using Student.class, we provide a Type. This Type is extracted from Gson's TypeToken, which is much analogous to Jackson's TypeReference:

// Instantiate FileReader for amy.json
Reader input = new FileReader("./src/main/resources/amy.json");
//Instantiate Gson
Gson gson = new Gson();
// Create a Type via TypeToken for the Student class
Type type = new TypeToken<Student>(){}.getType();
// Read the `input` and cast into `type`
Student amy = gson.fromJson(input, type);
// Print result
System.out.println(amy);
Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

This, surely enough also instantiates and populates our Student POJO:

Student{firstName='Amy', lastName='Winehouse', studentID=1328, email='[email protected]', courses=[Jazz, Blues], financeType=SUBSIDIZED}

Compact and Pretty Printing

By default, GSON prints the JSON in a compact format, which we've been able to see previously:

{"firstName":"Max","lastName":"Tegmark","studentID":1254,"email":"[email protected]","courses":["Physics 8.01","Physics 8.012"],"financeType":"SUBSIDIZED"}
{"firstName":"Amy","lastName":"Winehouse","studentID":1328,"email":"[email protected]","courses":["Jazz","Blues"],"financeType":"SUBSIDIZED"}

There are no whitespaces between field names and their values, object fields and objects within arrays. Additionally, not a single newline is present. If copied as a String - \n (newlines) will be present, though, this compact view is a a hassle to read.

We can turn on pretty-printing using Gson, fairly easily. When instantiating Gson, instead of calling the default, empty constructor - we can use the GsonBuilder() constructor:

Gson gson = new GsonBuilder().setPrettyPrinting().create();

Now, we can use the gson instance much the same way as we did before:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String amyJson = gson.toJson(amy);
System.out.println(amyJson);

Though, this time around, when printed - the JSON string has pretty-printing turned on:

{
  "firstName": "Amy",
  "lastName": "Winehouse",
  "studentID": 1328,
  "email": "[email protected]",
  "courses": [
    "Jazz",
    "Blues"
  ],
  "financeType": "SUBSIDIZED"
}

Naming JSON Fields with @SerializedName

Serialization is commonly used to transfer data between services - most notably, through REST APIs. When dealing with different services, teams or even languages that are processing the data we're providing - we might want to change the serialized names of certain fields to conform to more widely accepted standards, or to the standards of a certain service that'll be processing the data we provide.

For example, we might be providing JSON data from a Java service to a Python service. Java naming conventions follow CamelCase, while Python's naming conventions follow lowercase_with_underscores for non-constants and classes.

Knowing that we'll be providing our data to a service or person who might want to use different conventions, we can change the serialized names of our fields to not match the ones in our POJO, via the @SerializedName annotation:

public class Student {
    @SerializedName("first_name")
    private String firstName;
    @SerializedName("last_name")
    private String lastName;
    @SerializedName("student_id")
    private int studentID;
    @SerializedName("student_email")
    private String email;
    @SerializedName("student_courses")
    private List<String> courses;
    @SerializedName("student_finance_type")
    private FINANCE_TYPE financeType;

     // Getters, setters, constructor, toString()
}

Now, when serialized, these names will be used instead of our field names:

String amyJson = gson.toJson(amy);
System.out.println(amyJson);

Which results in:

{
  "first_name": "Amy",
  "last_name": "Winehouse",
  "student_id": 1328,
  "student_email": "[email protected]",
  "student_courses": [
    "Jazz",
    "Blues"
  ],
  "student_finance_type": "SUBSIDIZED"
}

This also works the other way around - if we receive JSON with first_name and our Student POJO has first_name mapped to firstName, we'll deserialize this just fine:

String input = "{\"first_name\":\"Amy\",\"last_name\":\"Winehouse\",\"student_id\":1328,\"student_email\":\"[email protected]\",\"student_courses\":[\"Jazz\",\"Blues\"],\"student_finance_type\":\"SUBSIDIZED\"}";
Gson gson = new Gson();
Student amy = gson.fromJson(input, Student.class);
System.out.println(amy);

This results in:

Student{firstName='Amy', lastName='Winehouse', studentID=1328, email='[email protected]', courses=[Jazz, Blues], financeType=SUBSIDIZED}

Conclusion

In this tutorial, we took a look at how to convert a Java Object into a JSON Object with Gson's toJson() method, as well as how to convert a JSON Object into a Java Object with Gson's fromJson() method.

We've also explored how to enable pretty-printing, as well as change the serialized names of fields.

Last Updated: June 15th, 2021
Was this article helpful?

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms