1
0

Jackson 2 to 3 migration companion code

Three Maven modules - jackson2-before (2.22.1), jackson3-after (3.2.1) and a
coexistence module with BOTH majors on one classpath - so every claim in the two
migration guides is executed rather than asserted. Paired class names make the
before/after outputs directly diffable via run-all.sh.

Confirms the guides on wire-format equivalence (10-case suite, zero mismatches),
classpath coexistence and the collapse of four artifacts into one. Corrects nine
points, including that enableDefaultTyping() is still present in Jackson 2.22.1
rather than removed in 2.16, and that the published "after" mapper snippet does
not compile.
This commit is contained in:
2026-08-04 23:12:25 +05:30
commit f0a7053fc9
43 changed files with 1665 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
output : {"id":1,"travelDate":"2026-09-15","seatPreference":"aisle"}
forked indented : { "id" : 1, "travelDate" : "2026-09-15", "seatPreference" : "aisle" }
original intact : false
set*() mutators : 0 <- mutation is impossible, not merely discouraged

View File

@@ -0,0 +1,5 @@
JacksonException extends RuntimeException : true
JacksonException extends IOException : false
ESCAPED catch (IOException) : StreamReadException
caught by catch (Jackson...) : StreamReadException
writeValueAsString declares : [class tools.jackson.core.JacksonException] <- nothing checked

View File

@@ -0,0 +1,3 @@
serialised : {"amount":19.99,"currency":"USD"}
deserialised : Money[amount=20.0, currencyCode=USD]
base classes : tools.jackson.databind.ValueSerializer / tools.jackson.databind.ValueDeserializer

View File

@@ -0,0 +1,4 @@
no modules : {"id":1,"departure":"2026-09-15","seat":"12A"}
round-trip : TravelPlan[id=1, departure=2026-09-15, seat=Optional[12A]]
dates : {"d":"2026-09-15"}
empty Optional : {"id":2,"departure":"2026-09-16","seat":null}

View File

@@ -0,0 +1,7 @@
enableDefaultTyping on Jackson 3 ObjectMapper : false
activateDefaultTyping on Jackson 3 ObjectMapper : false
activateDefaultTyping on JsonMapper.Builder : true
written : {"@class":"com.ankurm.migration.after.S05DefaultTyping$Envelope","body":{"@class":"com.ankurm.migration.after.S05DefaultTyping$SafePayload","note":"ok"}}
read : SafePayload[ok]
rogue : rejected with InvalidTypeIdException

View File

@@ -0,0 +1,9 @@
FAIL_ON_TRAILING_TOKENS : true
FAIL_ON_UNKNOWN_PROPERTIES : false
ALLOW_FINAL_FIELDS_AS_MUTATORS: false
DEFAULT_VIEW_INCLUSION : false
AUTO_DETECT_CREATORS exists : false
concatenated JSON -> rejected: MismatchedInputException
trailing garbage -> rejected: StreamReadException
unknown property -> accepted: OrderDto[orderId=1]

View File

@@ -0,0 +1,4 @@
output : {"id":1,"travelDate":"2026-09-15","seatPreference":"aisle"}
after mutation : { "id" : 1, "travelDate" : "2026-09-15", "seatPreference" : "aisle" }
mutation stuck : true
set*() mutators : 40

View File

@@ -0,0 +1,3 @@
JsonProcessingException extends IOException : true
caught by catch (IOException) : JsonParseException
writeValueAsString declares : [class com.fasterxml.jackson.core.JsonProcessingException]

View File

@@ -0,0 +1,3 @@
serialised : {"amount":19.99,"currency":"USD"}
deserialised : Money[amount=20.0, currencyCode=USD]
base classes : com.fasterxml.jackson.databind.JsonSerializer / com.fasterxml.jackson.databind.JsonDeserializer

View File

@@ -0,0 +1,4 @@
with modules : {"id":1,"departure":"2026-09-15","seat":"12A"}
round-trip : TravelPlan[id=1, departure=2026-09-15, seat=Optional[12A]]
bare mapper : FAILS -> InvalidDefinitionException
bare, dates only: FAILS -> InvalidDefinitionException

View File

@@ -0,0 +1,3 @@
enableDefaultTyping on Jackson 2.22 ObjectMapper : true
written : {"@class":"com.ankurm.migration.before.S05DefaultTyping$Envelope","body":{"@class":"com.ankurm.migration.before.S05DefaultTyping$SafePayload","note":"ok"}}
read : SafePayload[ok]

View File

@@ -0,0 +1,9 @@
FAIL_ON_TRAILING_TOKENS : false
FAIL_ON_UNKNOWN_PROPERTIES : true
ALLOW_FINAL_FIELDS_AS_MUTATORS: true
DEFAULT_VIEW_INCLUSION : true
AUTO_DETECT_CREATORS exists : true
concatenated JSON -> accepted: OrderDto[orderId=1]
trailing garbage -> accepted: OrderDto[orderId=1]
unknown property -> rejected: UnrecognizedPropertyException

View File

@@ -0,0 +1,12 @@
jackson 2 class : com.fasterxml.jackson.databind.ObjectMapper
jackson 3 class : tools.jackson.databind.json.JsonMapper
jackson 2 output: {"booking_id":1,"travel_date":"2026-09-15"}
jackson 3 output: {"booking_id":1,"travel_date":"2026-09-15"}
wire-compatible : true
3 reads 2's JSON: Booking[id=1, travelDate=2026-09-15]
2 reads 3's JSON: Booking[id=1, travelDate=2026-09-15]
annotation from : jackson-annotations-2.22.jar
<- one jackson-annotations jar, used by both majors

View File

@@ -0,0 +1,14 @@
plain record identical
nested list identical
map identical
java.time identical
Optional present identical
Optional empty identical
NON_NULL identical
@JsonProperty identical
@JsonFormat identical
nulls and empties identical
cases : 10
mismatches: 0
Wire format is identical across both majors for these cases.