1

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!

AlexGreg
  • 838
  • 10
  • 22

1 Answers1

1

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);
    }
}
Logan Pickup
  • 2,294
  • 2
  • 22
  • 29
  • well, lets say I want to map polymorphic geoJson data, so in my case the interface is `org.springframework.data.mongodb.core.geo.GeoJson` so I can't modify it. – AlexGreg May 22 '18 at 10:04
  • You can add decorator classes to Jackson for classes you can't modify: `mapper.addMixIn(GeoJson.class, GeoJsonMixin.class)` Where you create the `GeoJsonMixin` class to contain the annotations you need. – Logan Pickup May 23 '18 at 02:22
  • Is this the only way? – improbable Dec 25 '19 at 10:10