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: