Spring modelling: field as interface

220 Views Asked by At

Is there any way to put a field inside a document's model as interface? Example:

public class Foo {
    private String id;
    private Bar bar;
}

Where Bar is an interface with multiple implementations. Inside Bar there is a method signature String getType() which it tells me which implementation I can use in order to map the data from the DB.

I've tried different solutions (@ReadingConverter/@WiritingConverter, @JsonSerialize/@JsonDeserialize) with no results. Every time I get

Failed to instantiate [Bar]: Specified class is an interface

Any help? Thank you!

1

There are 1 best solutions below

3
Logan Pickup On

It looks like you want polymorphic serialisation/deserialisation. You should look at the Jackson docs for that: http://www.baeldung.com/jackson-advanced-annotations

In short, you'll want to do something like this, where a @JsonTypeIdResolver annotation is used to define a custom type resolver:

@JsonTypeInfo(use = @JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME, 
    include = JsonTypeInfo.As.PROPERTY, 
    property = "@type"
)
@JsonTypeIdResolver(BarTypeIdResolver.class)
public interface Bar {
    ...
}

public class BarTypeIdResolver extends TypeIdResolverBase {
    // boilerplate skipped, see the documentation
     
    @Override
    public String idFromValueAndType(Object obj, Class<?> subType) {
        String typeId = null;
        if (obj instanceof Bar) {
            Bar bar = (Bar) obj;
            typeId = bar.getType();
        }
        return typeId;
    }
 
    @Override
    public JavaType typeFromId(DatabindContext context, String id) {
        Class<?> subType = null;
        switch (id) {
        case "barImpl1":
            subType = BarImpl1.class;
            break;
            ...
        }
        return context.constructSpecializedType(superType, subType);
    }
}