package com.ankurm.jackson3.part2modernjava; import com.fasterxml.jackson.annotation.JsonInclude; import tools.jackson.databind.json.JsonMapper; import java.util.Optional; /** * Post: Jackson with Records, Optionals, Sealed Classes * https://ankurm.com/jackson-java-records-optionals/ * Section: "Jackson with Optional" * * Jackson 3 handles Optional natively. There is no jackson-datatype-jdk8 * dependency in the pom and no registerModule(new Jdk8Module()) call — those are * Jackson 2 requirements, and the Jdk8Module class does not exist under * tools.jackson at all. */ public class C02OptionalFields { public record CustomerProfile(String customerName, Optional middleName) { } /** NON_ABSENT is the inclusion value that understands Optional.empty(). */ @JsonInclude(JsonInclude.Include.NON_ABSENT) public record CompactProfile(String customerName, Optional middleName) { } public static void main(String[] args) { JsonMapper mapper = JsonMapper.builder().build(); // Present value: the Optional is unwrapped, not wrapped in {"present":true}. System.out.println("present : " + mapper.writeValueAsString(new CustomerProfile("Alice", Optional.of("Marie")))); // Empty Optional: serialises as null by default. System.out.println("empty : " + mapper.writeValueAsString(new CustomerProfile("Bob", Optional.empty()))); // NON_ABSENT omits the property entirely instead of writing null. System.out.println("absent : " + mapper.writeValueAsString(new CompactProfile("Bob", Optional.empty()))); // Deserialise back. String json = "{\"customerName\":\"Alice\",\"middleName\":\"Marie\"}"; CustomerProfile restored = mapper.readValue(json, CustomerProfile.class); System.out.println("isPresent: " + restored.middleName().isPresent()); // A missing property deserialises to Optional.empty(), never to null. CustomerProfile missing = mapper.readValue("{\"customerName\":\"Carol\"}", CustomerProfile.class); System.out.println("missing -> " + missing.middleName() + " (null? " + (missing.middleName() == null) + ")"); } }