Serialize an object to JSON using Jackson library
With the hint of OH GOD SPIDERS's, follow the answers to:
These are the 3 steps to use Jackson:
- add Jackson dependencies
jackson-core
, jackson-annotations
and jackson-databind
to your project, e.g. to Maven POM
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
- Create an
ObjectMapper
to use for JSON mapping (generation/parsing)
var mapper = new ObjectMapper();
// optional configuration
- pass your object instance to the suitable
write..
method
try {
// convert object to JSON string and print it
String json = mapper.writeValueAsString(person)
System.out.println(json);
}
catch (JsonGenerationException | JsonMappingException e) {
// catch various errors
e.printStackTrace();
}
ℹ️ Note: You need public getters so Jackson mapper can access and serialize to JSON.
Configure desired serialization
Exclude null, empty or absent values
To exclude null
values in written JSON, you can add the annotation @JsonInclude(Include.NON_NULL)
to your properties:
public class Data {
private String name;
private String age;
@JsonInclude(Include.NON_NULL)
private String job;
// getters and setters omitted
}
There are a few of similar ex-/inclusion options:
NON_ABSENT
Value that indicates that properties are included unless their value is: null "absent" value of a referential type (like Java 8 Optional
, or {link java.util.concurrent.atomic.AtomicReference}); that is, something that would not deference to a non-null value.
NON_EMPTY
Value that indicates that only properties with null value, or what is considered empty, are not to be included.
NON_NULL
Value that indicates that only properties with non-null values are to be included.
Conditional in-/exclusion
I want to create a list of people, but I want the attribute job
only to appear when the person is more than 30 years old.
Following are 2 ways to achieve this conditional serialization:
- [KISS] a "quick and dirty" solution
- [SOLID] a safe and maintainable design
[KISS] Simple modification of default getter
Assume the class Data
is only used for the JSON-representation (what we call a DTO).
Then I would solve this simply by implementing a conditional getter like:
public class Data {
private String name;
private String age;
@JsonInclude(Include.NON_NULL)
private String job;
public String getJob() {
// exclude in JSON if 30 or younger
if (Integer.valueOf(age) <= 30) {
return null;
}
return job;
}
// remaining getters and setters omitted
}
⚠️ Warning: This modification breaks the conventional behavior of Java-getters. They should be free of conditions. Thus I added a comment to explain the "why" and kept the if-block easily removable to undo.
[SOLID] Add a custom accessor
Clean-code (expressive/additive) that follows design-principles (SRP/OCP) as recommended by Reilas would:
- keep
getJob
as your accessor, and
- make a different method to provide the conditional check, call it
job
or jobIfOver30
.
Example:
private String job;
// other fields and getters omitted to focus on custom property serialization
@JsonIgnore // 1. ignore the original property to keep accessor
public String getJob() {
return job;
}
@JsonProperty("job") // 2. conditional serialization with original name
@JsonInclude(Include.NON_NULL)
public String jobIfOver30() {
if (Integer.valueOf(age) > 30) {
return job;
}
return null;
}
️ Benefit: We don't need a comment and can invert the if-statement because the added method has
- a single responsibility (JSON serialization only) and
- a self-expressive name.
See also
Unfortunately not the case here, but when the condition depends only on values of the same property, you could use the @JsonInclude
annotation with CUSTOM
option as explained in: