Jackson 3 and final Map deserialization

12 hours ago 4
ARTICLE AD BOX

In a corporate project, I’m migrating from Spring 3.x to Spring 4.x, and also from Jackson 2.x to 3.x at the same time.

I do have the following problem: with Jackson 2 this code works "as is", but I cannot find the way to make it work with Jackson 3, as the content field is not detected by Jackson.

What am I missing to make it work?

Sample code (can be run via an IDE JShell for convenience):

import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.json.JsonMapper; import java.io.Serializable; import java.util.*; abstract class BaseMessage { protected UUID id; protected final Map<String, Serializable> content; // And other fields… protected BaseMessage() { id = UUID.randomUUID(); content = new HashMap<>(); } public <T extends Serializable> void addContent(final String key, final T value) { content.put(key, value); } public <T extends Serializable> void addContent(final Map<String, T> contentToAdd) { content.putAll(contentToAdd); } public <T extends Serializable> void overrideContent(final Map<String, T> newContent) { content.clear(); content.putAll(newContent); } public void setId(final UUID id) { this.id = id; } public UUID getId() { return id; } public Map<String, Serializable> getContent() { return content; } } class ClientMessage extends BaseMessage { private String upn; // And other fields and methods… public void setUpn(final String upn) { this.upn = upn; } @Override public String toString() { return "ClientMessage{" + "upn='" + upn + "', id=" + id + ", content=" + content + '}'; } } final String jsonMessage = """ { "id": "00000000-0000-0000-0000-000000000000", "content": { "test": true, "prod": false, "demo": "Demonstration" }, "upn": "[email protected]" }"""; // I do enable voluntarily the `FAIL_ON_UNKNOWN_PROPERTIES` to highlight the problem with Jackson 3+. JsonMapper.builder() .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // ↓ Added as otherwise it’s included in the error message, but it doesn’t help anyway… .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION .build() .readValue(jdonMessage, ClientMessage.class);

Actual result:

Unrecognized property "content" (class ClientMessage), not marked as ignorable (2 known properties: "id", "upn")
at [Source: (String)"{
"id": "00000000-0000-0000-0000-000000000000",
"content": {
"test": true,
"prod": false,
"demo": "Demonstration"
},
"upn": "[email protected]"
}"; line: 3, column: 15] (through reference chain: ClientMessage["content"])

Jackson 2 (partial version):

import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; // […] new ObjectMapper() .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .readValue(jsonMessage, ClientMessage.class)

Actual (and expected for Jackson3+) result:

[…] = ClientMessage{upn='[email protected]', id=00000000-0000-0000-0000-000000000000, content={test=true, prod=false, demo=Demonstration}}

Read Entire Article