1
0
Ankur ef05f9024e 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:12:11 +05:30
2026-08-04 23:12:11 +05:30
2026-08-04 23:12:11 +05:30
2026-08-04 23:12:11 +05:30
2026-08-04 23:12:11 +05:30
2026-08-04 23:12:11 +05:30

jackson3-by-example

Runnable companion code for the eight-part Jackson 3 series on ankurm.com.

Every example is a standalone main() you can run on its own. Every line of output in docs/ was produced by run-all.sh on the versions below — nothing is transcribed by hand.

Jackson            3.2.1        (tools.jackson.core:jackson-databind)
jackson-annotations 2.22        (com.fasterxml.jackson.core — deliberately unchanged)
JDK                Temurin 21.0.5
Maven              3.9.9

Run it

git clone https://ankurm.com/git.app/asmhatre/jackson3-by-example.git
cd jackson3-by-example
./run-all.sh                       # compiles, runs all 37 examples, refreshes docs/output/

Or run any single example:

mvn -q compile
mvn -q exec:java -Dexec.mainClass=com.ankurm.jackson3.part5polymorphic.F01SerialiseMixedList

Map: post → code

Post Package Examples
Jackson 101 part0setup A01 A02 A03
ObjectMapper Guide part1objectmapper B01 B02 B03 B04
Records, Optionals, Sealed part2modernjava C01 C02 C03 C04
Annotations Cheat Sheet part3annotations D01 D02 D03 D04
Custom Serialisers & Mix-ins part4custom E01 E02 E03 E04 E05
Polymorphic Deserialisation part5polymorphic F01 F02 F03 F04
Streaming API & JsonNode part6streaming G01 G02 G03 G04
Security Best Practices part7security H01 H02 H03 H04 H05
— (beyond the posts) beyond Y01 Y02 Y03 Y04 Y05 Y06

Per-part write-ups with the captured output live in docs/.

Corrections to the posts

Writing this code against a real Jackson 3.2.1 build surfaced places where the blog snippets do not compile or do not behave as printed. Each is demonstrated by a program, so you can verify rather than take my word for it.

# Claim in the post What actually happens Shown by
1 Maven coordinate com.fasterxml.jackson.core:jackson-databind:3.1.2 That artifact does not exist. Jackson 3 is at tools.jackson.core:jackson-databind; only jackson-annotations keeps the old group ID. pom.xml
2 JsonMapper.builder().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) Does not compile. The constant is not on SerializationFeature in Jackson 3 — it moved to tools.jackson.databind.cfg.DateTimeFeature, and it already defaults to off, so ISO-8601 needs no configuration. Y03
3 JsonMapper.builder().serializationInclusion(...) No such builder method. The real API is changeDefaultPropertyInclusion(UnaryOperator). A02, H02
4 writeValueAsString(List<PaymentMethod>) emits paymentType It does not. A List carries no element type, so the polymorphic serialiser never engages and the discriminator is dropped — and the output then fails to deserialise. Use writerFor(TypeReference) or a typed array. F01, F02
5 Remediate with mapper.activateDefaultTyping(validator, ...) Jackson 3's mapper has no mutators at all — not enableDefaultTyping, not activateDefaultTyping, not one set* method. activateDefaultTyping exists only on JsonMapper.Builder. H02, H03
6 import tools.jackson.core.JsonFactory Wrong package. It is tools.jackson.core.json.JsonFactory. G01
7 Optional needs jackson-datatype-jdk8; records need jackson-module-parameter-names and -parameters All three are built into jackson-databind 3.x. The Jackson 2 module classes do not exist under tools.jackson, so leaving the registrations in place is a compile error. C01, C02
8 Set FAIL_ON_UNKNOWN_PROPERTIES=false; use @JsonIgnoreProperties(ignoreUnknown=true) to opt out per class Already false by default in Jackson 3. The annotation now matters only when you deliberately turn strictness back on. D03
9 Without @JsonFormat, LocalDate is written as a numeric array Jackson 2 behaviour. Jackson 3 writes ISO-8601 by default; the annotation is only needed for a non-standard pattern. D02
10 Removing AUTO_DETECT_CREATORS means single-arg constructors "quietly fail" The enum constant is gone, but the behaviour is not: a single-argument constructor is still detected as a delegating creator. Annotate anyway, but the upgrade will not break these classes. Y05
11 The custom deserialiser uses p.getCodec().readTree(p) and node.get(...) getCodec() is gone — use ctxt.readTree(parser). And get() NPEs on a missing field; path() with a defaulting accessor does not. A bare decimalValue() on a MissingNode throws in Jackson 3 where Jackson 2 returned zero. E02, E03

Two smaller ones worth knowing, neither strictly an error in the posts:

  • A getter-based POJO serialises its properties alphabetically; a record serialises in declaration order. The post's sample output for ProductSummary shows declaration order. See B04.
  • {"amount":20.00} deserialises to BigDecimal 20.0, not 20.00 — the scale is lost unless USE_BIG_DECIMAL_FOR_FLOATS is enabled. See E03.

Measured, not asserted

Three examples produce numbers rather than prose. Figures below are from one run on a 2-core container; re-run them on your own hardware.

Three processing models over a 20 MB / 200k-entry file (G04):

data binding (readValue)     errors=4000      424 ms   heap delta    46 MB
tree model (readTree)        errors=4000      290 ms   heap delta   101 MB
streaming (JsonParser)       errors=4000       79 ms   heap delta     0 MB

Streaming a million records (G02): 30 MB written in 124 ms with a 0 MB heap delta.

RecyclerPool (Y06) — the comparison post suggests restoring the 2.x thread-local pool if you see a regression. On this box that advice holds under concurrency and is a wash single-threaded:

1 thread    threadLocalPool 317 ms   concurrentDeque 317 ms   nonRecycling 342 ms
8 threads   threadLocalPool 328 ms   concurrentDeque 416 ms   nonRecycling 935 ms
Description
Runnable companion code for the 8-part Jackson 3 series on ankurm.com. 37 standalone programs on Jackson 3.2.1 / JDK 21 — ObjectMapper, records, Optional, sealed types, annotations, custom ValueSerializers, mix-ins, polymorphism, streaming and the tree model, security hardening — plus corrections where the real Jackson 3 API differs from the posts. Every output in the docs was produced by run-all.sh.
Readme 254 KiB
Languages
Java 99%
Shell 1%