# Part 2 — Records, Optionals and sealed types Post: The single biggest simplification in Jackson 3 lands here. All three features are in core: the project's [`pom.xml`](../pom.xml) has one dependency, no `jackson-datatype-jdk8`, no `jackson-module-parameter-names`, and no `-parameters` compiler argument. ## C01 — records [`C01RecordRoundTrip.java`](../src/main/java/com/ankurm/jackson3/part2modernjava/C01RecordRoundTrip.java) ``` {"productId":101,"productName":"Wireless Keyboard","unitPrice":49.99} Wireless Keyboard round-trip equal: true ``` The post's own dependency block here is wrong twice over: it suggests `com.fasterxml.jackson.module:jackson-module-parameter-names:3.1.2`, which is both an artifact Jackson 3 does not need and a version that does not exist at that coordinate. ## C02 — Optional [`C02OptionalFields.java`](../src/main/java/com/ankurm/jackson3/part2modernjava/C02OptionalFields.java) ``` present : {"customerName":"Alice","middleName":"Marie"} empty : {"customerName":"Bob","middleName":null} absent : {"customerName":"Bob"} isPresent: true missing -> Optional.empty (null? false) ``` Two behaviours worth committing to memory: an empty `Optional` serialises as `null` unless you ask for `NON_ABSENT`, and a *missing* property deserialises to `Optional.empty()` rather than to `null`, so the field is never null. ## C03 — sealed types with an explicit registry [`C03SealedWithSubTypes.java`](../src/main/java/com/ankurm/jackson3/part2modernjava/C03SealedWithSubTypes.java) ``` Circle with radius: 5.0 Rectangle 10.0 x 4.0 lossy : [{"radius":5.0},{"width":10.0,"height":4.0}] correct : [{"shapeType":"circle","radius":5.0},{"shapeType":"rectangle","width":10.0,"height":4.0}] ``` Note the `lossy` line. Serialising a `List` drops the `shapeType` discriminator, because a `List` gives Jackson no element type to dispatch on. This is the same defect covered at length in [Part 5](part5-polymorphic.md). ## C04 — sealed auto-discovery [`C04SealedAutoDiscovery.java`](../src/main/java/com/ankurm/jackson3/part2modernjava/C04SealedAutoDiscovery.java) Beyond the post: Jackson 3 reads the `permits` clause, so `@JsonSubTypes` can be dropped entirely when each permitted type carries `@JsonTypeName`. There is no `@JsonSubTypes` anywhere in that file, and a third subtype added later just works. ``` Circle -> {"shapeType":"circle","radius":5.0} -> Circle[radius=5.0] Rectangle -> {"shapeType":"rectangle","width":10.0,"height":4.0} -> Rectangle[width=10.0, height=4.0] Triangle -> {"shapeType":"triangle","base":3.0,"height":6.0} -> Triangle[base=3.0, height=6.0] ``` In Jackson 2 the `@JsonSubTypes` registry had to be maintained in parallel with `permits`, and drifted whenever someone added a case.