# 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.