Джексон бросить JsonMappingException не может создать экземпляр - PullRequest
0 голосов
/ 05 сентября 2018

// интерфейс

public interface NotificationPayload {
}

// Классы реализуют интерфейс

public ClassA implements NotificationPayload {...}
public ClassB implements NotificationPayload {...}
...
public ClassX implements NotificationPayload {...}

// Сообщение для отправки

public class Notification<T extends NotificationPayload> {
    private T data; //T may be ClassA/ClassB/ClassC.../ClassX
    ...
}

Когда я получаю сообщение как json, я хочу снова преобразовать его в Уведомление, используя ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)

json пример:

{
    "type":"ClassA",
    "userId":10087
}

Я конвертирую это:

Notification notif = objectMapper.readValue(json, Notification.class);

это исключение:

java.lang.IllegalArgumentException: Can not construct instance of 
com.common.kafka.notification.NotificationPayload: abstract types
either need to be mapped to concrete types, have custom deserializer, or
contain additional type information
at [Source: N/A; line: -1, column: -1] (through reference chain:
com.common.kafka.notification.Notification["data"])

Я читал из этого вопроса: Невозможно создать экземпляр - Джексона , но похоже, что это не может помочь, потому что у меня слишком много классов, реализованных из интерфейса, не только один раз.

1 Ответ

0 голосов
/ 06 сентября 2018

Вам нужно использовать аннотацию Джексона для достижения полиморфной десериализации.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = ClassA.class, name = "ClassA"),
        @JsonSubTypes.Type(value = ClassB.class, name = "ClassB")
})
public interface NotificationPayload {
}

public class ClassA implements NotificationPayload {

    private Integer userId;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}

public class Notification <T extends NotificationPayload> {

    private T data; //T may be ClassA/ClassB/ClassC.../ClassX

    @JsonCreator
    public Notification(T data) {
        this.data = data;
    }

    public static void main(String[] args) throws IOException {

        String jsonStr = "{\"type\":\"ClassB\",\"userId\":10087}";

        ObjectMapper objectMapper = new ObjectMapper();
        Notification notification = objectMapper.readValue(jsonStr, Notification.class);
    }
}

Все аннотации вы можете найти здесь

...