How to learn Jackson to cast inheritors of abstract class?

Вячеслав Чернышов :

I have a class:

@EqualsAndHashCode(callSuper = true)
@Data
public class AppealTemplateDto extends AbstractDto {

    private List<AbstractFieldDto> fields;
}

This class contains list of AbstractFieldDto inheritors, e.g.:

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class InputFieldDto extends AbstractFieldDto {

    private String fieldType = FieldType.INPUT.name();
    private String text;
}

Totally, there are near 6-7 inheritors, & AbstractTemplateDto may contain any set of them.

Controller:

@PostMapping
public ResponseEntity<AppealTemplateDto> create(@RequestBody AppealTemplateDto dto) {
    return ResponseEntity.ok(service.save(dto));
}

When Jackson trying to parse AppealTemplateDto, it crashes with exception:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of ru.appeal.template.dto.field.AbstractFieldDto (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

As I understand, Jackson can't define, how to cast incoming AbstractFieldDto. Please, advice me, what to do?

pdem :

The Annotation your are needing are:

@JsonTypeInfo
@JsonSubType

@JsonTypeName

Some explanation: if you have many implementation of your abstract type, Jackson can't guess which type is your json, you need to add a type name in json, for example as a new property (this is one of the strategies):

//tell to jackson where to find the type name
@JsonTypeInfo(   use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
// tell to jackson the implementations to scan
@JsonSubTypes({
    @JsonSubTypes.Type(value = InputFieldDto.class, name = "input")
    //, ...
})
public class AbstractFieldDto {
}

//tell to jackson what is the type name in json
@JsonTypeName("input")
public class InputFieldDto extends AbstractFieldDto {

    private String fieldType = FieldType.INPUT.name();
    private String text;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=156587&siteId=1