1
0
Files
jackson3-by-example/docs/part3-annotations.md
Ankur c438afc33b 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.
2026-08-04 23:29:26 +05:30

75 lines
3.1 KiB
Markdown

# Part 3 — Annotations
Post: <https://ankurm.com/jackson-annotations-guide/>
Every `@Json*` annotation is imported from `com.fasterxml.jackson.annotation`, even in
Jackson 3. `jackson-annotations` deliberately keeps the old group ID and package so a
single copy can serve Jackson 2 and Jackson 3 code on one classpath — the
[migration repo's coexistence module](https://ankurm.com/git.app/asmhatre/jackson2-to-3-migration)
proves that with both majors loaded at once.
## D01 — @JsonProperty and @JsonIgnore
[`D01RenameAndIgnore.java`](../src/main/java/com/ankurm/jackson3/part3annotations/D01RenameAndIgnore.java)
```
rename : {"order_id":1001,"customer_name":"Alice"}
read back : OrderSummary[orderId=1001, customerName=Alice]
ignore : {"username":"alice"}
read back : passwordHash=null
```
`@JsonIgnore` is bidirectional — the last line shows an injected `passwordHash` in the
input being discarded, which is the security-relevant half people forget.
## D02 — @JsonInclude and @JsonFormat
[`D02InclusionAndFormat.java`](../src/main/java/com/ankurm/jackson3/part3annotations/D02InclusionAndFormat.java)
```
NON_NULL : {"productName":"Keyboard"}
NON_EMPTY : {"productName":"Keyboard"}
formats : {"invoiceId":500,"defaultDate":"2026-04-09","ukStyleDate":"09/04/2026","totalAmount":"199.99"}
```
`defaultDate` carries no annotation and still comes out as `2026-04-09`. The post's
claim that "without `@JsonFormat`, Jackson writes `LocalDate` as a numeric array" was
true in Jackson 2; in Jackson 3 ISO-8601 is the default and the annotation is only
needed for a non-standard pattern such as `ukStyleDate`.
## D03 — @JsonAlias and unknown fields
[`D03AliasAndUnknownFields.java`](../src/main/java/com/ankurm/jackson3/part3annotations/D03AliasAndUnknownFields.java)
```
alias {"q":"jackson"} -> jackson
alias {"query":"jackson"} -> jackson
alias {"search_term":"jackson"} -> jackson
default mapper : LenientResponse[status=OK, message=done]
strict mapper : UnrecognizedPropertyException (as expected)
strict + anno : OptedOutResponse[status=OK, message=done]
```
The post frames `@JsonIgnoreProperties(ignoreUnknown = true)` as the per-class
alternative to disabling `FAIL_ON_UNKNOWN_PROPERTIES` globally. In Jackson 3 that
feature is already off, so the default mapper tolerates the extra field with no
annotation. The annotation earns its keep only on a mapper where you have deliberately
re-enabled strictness — which is the `strict` case above.
## D04 — creators, unwrapping and catch-alls
[`D04CreatorsAndUnwrapping.java`](../src/main/java/com/ankurm/jackson3/part3annotations/D04CreatorsAndUnwrapping.java)
`@JsonUnwrapped` appears in the post's summary table but is never demonstrated;
`@JsonAnyGetter`/`@JsonAnySetter` are not in the post at all, and are the cleanest way
to keep fields you did not model instead of silently dropping them.
```
creator : ImmutablePoint(x=3.5, y=7.2)
round-trip: {"x":3.5,"y":7.2}
unwrapped : {"street":"123 Main St","city":"Springfield","customerName":"Alice"}
any-setter: {surprise=1, another=[true, false]}
any-getter: {"knownField":"a","surprise":1,"another":[true,false]}
```