Wrap Nullable Java Fields with Optional<T>
Use Optional<T> for fields that may legitimately be missing or null in JSON. Learn the trade-offs between Optional, nullable boxed types, and the @JsonInclude(NON_NULL) approach.
Detailed Explanation
Optional for Nullable JSON Fields
JSON does not distinguish between "missing" and "explicitly null", but Java code often needs to. java.util.Optional<T> is one way to make absence explicit at the type level.
Example JSON
{
"id": 1,
"username": "alice",
"email": "alice@example.com",
"phone": null
}
Java POJO with Optional
package com.example.model;
import java.util.Optional;
public class User {
private Integer id;
private String username;
private String email;
private String phone; // store as String
public Optional<String> getPhone() {
return Optional.ofNullable(phone);
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Important: Use Optional Only on Getters
The official guidance from the Optional designers (JEP 269) is to not use Optional as a field type. Instead, store a nullable reference and return Optional from the getter. Reasons:
Optionalis notSerializable- Jackson cannot deserialize directly into an Optional field without extra configuration
- Optional adds a wrapper allocation per access
Configuring Jackson for Optional
If you do choose to use Optional in fields, add the jackson-datatype-jdk8 module:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
ObjectMapper mapper = new ObjectMapper().registerModule(new Jdk8Module());
Alternatives to Optional
- Nullable boxed types — the default.
Integerinstead ofint, check fornullat the call site. - @JsonInclude(NON_NULL) — exclude null fields from serialization output.
- Default values — initialize fields to sensible defaults (e.g., empty list, zero) and never serialize null.
Optional in Records
Records can return Optional from accessor overrides:
public record User(Integer id, String username, String email, String phone) {
public Optional<String> phone() {
return Optional.ofNullable(phone);
}
}
This preserves the canonical constructor while exposing a nullable-aware API.
Use Case
Service-layer code that needs to handle missing data without scattering null checks benefits from Optional return types. API responses with rarely-populated fields (alternate phone, secondary email, custom metadata) are textbook use cases.