I want to serialize and deserialize an immutable object using com.fasterxml.jackson.databind.ObjectMapper.
The immutable class looks like this (just 3 internal attributes, getters and constructors):
public final class ImportResultItemImpl implements ImportResultItem { private final ImportResultItemType resultType; private final String message; private final String name; public ImportResultItemImpl(String name, ImportResultItemType resultType, String message) { super(); this.resultType = resultType; this.message = message; this.name = name; } public ImportResultItemImpl(String name, ImportResultItemType resultType) { super(); this.resultType = resultType; this.name = name; this.message = null; } @Override public ImportResultItemType getResultType() { return this.resultType; } @Override public String getMessage() { return this.message; } @Override public String getName() { return this.name; } }
However when I run this unit test:
@Test public void testObjectMapper() throws Exception { ImportResultItemImpl originalItem = new ImportResultItemImpl("Name1", ImportResultItemType.SUCCESS); String serialized = new ObjectMapper().writeValueAsString((ImportResultItemImpl) originalItem); System.out.println("serialized: " + serialized); //this line will throw exception ImportResultItemImpl deserialized = new ObjectMapper().readValue(serialized, ImportResultItemImpl.class); }
I get this exception:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class eu.ibacz.pdkd.core.service.importcommon.ImportResultItemImpl]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: {"resultType":"SUCCESS","message":null,"name":"Name1"}; line: 1, column: 2] at ... nothing interesting here
This exception asks me to create a default constructor, but this is an immutable object, so I don’t want to have it. How would it set the internal attributes? It would totally confuse the user of the API.
So my question is: Can I somehow de/serialize immutable objects without default constructor?
Advertisement
Answer
To let Jackson know how to create an object for deserialization, use the @JsonCreator
and @JsonProperty
annotations for your constructors, like this:
@JsonCreator public ImportResultItemImpl(@JsonProperty("name") String name, @JsonProperty("resultType") ImportResultItemType resultType, @JsonProperty("message") String message) { super(); this.resultType = resultType; this.message = message; this.name = name; }