How to properly deserialize an object from JSON (using Jackson) when it has an abstract property of which the conrete implementation depends on another property from that request body?
This is probably best described on an example.
Request body for my REST endpoint includes a property which is an abstract type with multiple concrete implementations which should be deserialized based on the discriminator
property:
@Getter
@Builder
@AllArgsConstructor
public class SomeRequestBody {
@NotNull
@NotBlank
@NumberFormat
private final String discriminator;
@NotNull
private final SomeAbstractClass someAbstractClass;
}
Abstract class in question
@Getter
@AllArgsConstructor
public abstract class SomeAbstractClass{
@NotNull
@NotBlank
protected final String commonProperty;
}
Example implementation of the abstract class
@Getter
public class ConcreteImplementationA extends SomeAbstractClass {
@Builder
@JsonCreator
public ConcreteImplementationA(
@NotNull @NotBlank @JsonProperty("commonProperty") String commonProperty,
@NotNull @NotBlank @JsonProperty("specificProperty") Date specificProperty) {
super(commonProperty);
this.specificProperty = specificProperty;
}
@NotNull
@NotBlank
private final String specificProperty;
}
What I tried...
@Getter
@Builder
@AllArgsConstructor
public class SomeRequestBody {
@NotNull
@NotBlank
@NumberFormat
private final String discriminator;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "discriminator")
@JsonSubTypes({
@JsonSubTypes.Type(value = ConcreteImplementationA.class, name = "1"),
Other implementations...)
})
@NotNull
private final SomeAbstractClass someAbstractClass;
}
However, I'm getting the following exception:
"Type definition error: [simple type, class abc.SomeRequestBody]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `abc.SomeRequestBody`, problem: Internal error: no creator index for property 'someAbstractClass' (of type com.fasterxml.jackson.databind.deser.impl.FieldProperty)\n at [Source: (PushbackInputStream); line: 8, column: 1]"
What is the proper way to achieve what I need?
Turns out it was not a problem with deserialization of that abstract property, but immutable properties and Lombok's @AllArgsConstructor
not working well with Jackson. I have created a @JsonCreator annotated constructor instead of using the annotation and now it works fine.