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

3.1 KiB

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 proves that with both majors loaded at once.

D01 — @JsonProperty and @JsonIgnore

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

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

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

@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]}