Jackson with Java Records, Optionals, and Sealed Classes (Java 21+)
Modern Java — particularly Java 16 through 21 — introduced several language features that change how you model data: Records for immutable value objects, Optional for nullable return types, and Sealed Classes for closed type hierarchies. Each of these interacts with Jackson in ways that require specific setup. This guide shows you exactly what to configure so that Jackson handles all three correctly. Runnable code: every example below is in the jackson3-by-example repository, compiled and executed against Jackson 3.2.1 on JDK 21 — C01 records, C02 Optional, C03 sealed types and C04 sealed auto-discovery without @JsonSubTypes, with captured output in docs/part2-modern-java.md. Jackson with Java Records Java Records are ideal DTOs: they are immutable, concise, and carry their own equals(), hashCode(), and toString() implementations. Jackson 3 supports Records natively with zero additional modules — the canonical constructor is used automatically for deserialisation and record accessor methods replace getters for serialisation. Define a Record: // A concise, immutable data transfer object public record ProductRecord( Long productId, String productName, double unitPrice ) {}