Jackson is a very common library for handling JSON and serialization/deserialization in general in Java and Spring Boot based projects.
Jackson handles property names by mapping them as they are to JSON - so
propertyName
in a POJO will have a correspondingpropertyName
in JSON. This convention is followed when converting JSON to POJO as well, and if the names don't match, the conversion can't be done.
However, there are many cases in which you'd want the serialized JSON properties to have different names, such as standardizing naming conventions for other services (using cases like snake_case
, instead of CamelCase
) or conflicting property names (a Customer
can have a firstName
, just as an Agent
- and a report may contain both of their firstName
properties and needs to be serialized).
Let's create a Book
class, with a few simple fields:
public class Book {
private String title;
private String author;
private int releaseYear;
public Book() {}
public Book(String title, String author, int releaseYear) {
this.title = title;
this.author = author;
this.releaseYear = releaseYear;
}
// Getters, setters, toString(), etc.
}
Change JSON Field Names with Jackson
When usually converting an instance of a Book
into JSON, we'd write the value of the object as a JSON string using ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);
String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);
This results in:
{"title":"Our Mathematical Universe","author":"Max Tegmark","releaseYear":2014}
The title
, author
and releaseYear
are a 1-to-1 mapping to the title
, author
and releaseYear
fields of the POJO. To change the name of a JSON property and retain it after serialization, there's no need to change your POJO! It's enough to annotate the relevant field with @JsonProperty
, and supply the JSON name:
public class Book {
@JsonProperty("book_title")
private String title;
@JsonProperty("book_author")
private String author;
@JsonProperty("book_release_year")
private int releaseYear;
public Book(){}
public Book(String title, String author, int releaseYear) {
this.title = title;
this.author = author;
this.releaseYear = releaseYear;
}
// Getters, setters, toString(), etc.
}
Now, when we instantiate the object and convert it to JSON:
ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);
String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);
The code results in:
{"book_title":"Our Mathematical Universe","book_author":"Max Tegmark","book_release_year":2014}
Change JSON Field Names in JSON-to-POJO Conversion?
It's worth noting that the name change isn't one-sided. The same annotation works both ways, and can bridge an incoming JSON with different names into a valid object. For instance, a JSON representing a book with book_title
, wouldn't be mapped to the title
property of the Book
class by default, as they aren't the same.
Since we've annotated title
as book_title
- the conversion works just fine:
Book bookReconstructed = mapper.readValue(jsonBook, Book.class);
System.out.print(bookReconstructed);
This results in:
Book{title='Our Mathematical Universe', author='Max Tegmark', releaseYear=2014}
Note: To construct an object from JSON, your class needs to have an empty constructor as well. Jackson first instantiates the empty object, and then populates the fields using the getters and setters.
Annotate Getters and Setters with @JsonProperty
Do you want to encode different names for serialization and deserialization? For instance, you can serialize Book
into a JSON with bt
denoting the book's title, but consume JSON with book_title
. You can customize the getters and setters of the Book
class with @JsonProperty
annotations:
@JsonProperty("bt")
public String getBt() {
return title;
}
@JsonProperty("book_title")
public void setTitle(String title) {
this.title = title;
}
This way, when serialized, the getBt()
method will serialize the title
as a bt
field in JSON. When reading from JSON (deserializing), you'll need to supply a book_title
, that gets mapped to title
.
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!
Note: Both bt
and book_title
will be mapped to the title
field, but this doesn't make bt
and book_title
interchangeable. Jackson won't be able to convert between them without first converting to title
.
Now, you can instantiate a book, serialize it, and deserialize another String into a book with:
ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);
// Serialization
String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);
// Deserialization
String input = "{\"author\":\"Max Tegmark\",\"releaseYear\":2017,\"book_title\":\"Life 3.0\"}";
Book bookReconstructed = mapper.readValue(input, Book.class);
System.out.print(bookReconstructed);
This results in:
{"author":"Max Tegmark","releaseYear":2014,"bt":"Our Mathematical Universe"}
Book{title='Life 3.0', author='Max Tegmark', releaseYear=2017}
Conclusion
In this short tutorial, we've taken a look at how Jackson maps object fields to JSON, and how you can change the name of the fields before serialization. We've also explored the idea of using different JSON names for serialization and deserialization, using the @JsonProperty
annotation on method-level, rather than field-level.