Jackson 3 series companion code
37 runnable examples covering the eight feature posts on ankurm.com, verified against Jackson 3.2.1 on Temurin 21.0.5. Every output committed under docs/ was produced by run-all.sh. Also documents 11 places where the published snippets do not compile or do not behave as printed against a real Jackson 3 build - most notably that writeValueAsString(List<Base>) silently drops the polymorphic type discriminator, so the post's serialised output cannot be read back.
This commit is contained in:
70
docs/part2-modern-java.md
Normal file
70
docs/part2-modern-java.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Part 2 — Records, Optionals and sealed types
|
||||
|
||||
Post: <https://ankurm.com/jackson-java-records-optionals/>
|
||||
|
||||
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<Shape>` 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.
|
||||
Reference in New Issue
Block a user