Подтвердить что ты не робот

Как де-/сериализовать неизменяемый объект без конструктора по умолчанию с помощью ObjectMapper?

Я хочу сериализовать и десериализовать неизменяемый объект, используя com.fasterxml.jackson.databind.ObjectMapper.

Неизменяемый класс выглядит следующим образом (всего 3 внутренних атрибута, геттеры и конструкторы):

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;
    }
}

Однако, когда я запускаю этот 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);
}

Я получаю это исключение:

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

Это исключение просит меня создать конструктор по умолчанию, но это неизменный объект, поэтому я не хочу его использовать. Как бы он установил внутренние атрибуты? Это полностью запутало бы пользователя API.

Итак, мой вопрос: Могу ли я как-то де-серизировать неизменяемые объекты без конструктора по умолчанию?

4b9b3361

Ответ 1

Чтобы Джексон знал, как создать объект для десериализации, используйте @JsonCreator и @JsonProperty аннотации для ваших конструкторов, например:

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

Ответ 2

Вы можете использовать собственный конструктор по умолчанию, затем Джексон заполнит поля с помощью отражения, даже если они являются закрытыми.

EDIT: используйте защищенный по умолчанию конструктор по умолчанию для родительских классов, если у вас есть наследование.