Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to inject Jackson annotation values from a meta annotation, similar to Spring's AliasFor annotation?

We're using @JacksonAnnotationsInside and would like to inject a property from the classes using the meta annotation.

i.e. we have a meta annotation with @JsonTypeInfo() and would like to inject the defaultImpl via the aggregating annotation.

Here is the annotation I'm trying to use:

@Inherited
@JacksonAnnotationsInside
@Retention(RetentionPolicy.RUNTIME)
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") //, defaultImpl=defaultType())
public @interface PolymorphismSupport {
    //@AliasFor("defaultImpl") ...
    Class<?> defaultType() default Object.class;
}
like image 210
dev_feed Avatar asked May 30 '18 20:05

dev_feed


1 Answers

The AliasFor like support is not available in Jackson.But as an workaround we can modify the consumption of metadata supplied by annotation by extending JacksonAnnotationIntrospector.

What you are trying to achieve can be done by providing an custom JacksonAnnotationIntrospector which will supply the default implementation from the PolymorphismSupport annotation.

@Inherited
@JacksonAnnotationsInside
@Retention(RetentionPolicy.RUNTIME)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public @interface PolymorphismSupport {

    Class<?> defaultType() default Object.class;

}

public class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {

    @Override
    protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config, Annotated ann, JavaType baseType) {
        TypeResolverBuilder<?> b = super._findTypeResolver(config, ann, baseType);
        PolymorphismSupport support = _findAnnotation(ann, PolymorphismSupport.class);
        if (null != b && null != support) {
            b.defaultImpl(support.defaultType());
        }
        return b;
    }
}


public class CustomObjectMapper extends ObjectMapper {

    public CustomObjectMapper() {
        setAnnotationIntrospector(new CustomAnnotationIntrospector());
    }
}

The only downside with this approach is that you have to register the introspector into the object mapper when initializing.

like image 61
Raghu Avatar answered Oct 05 '22 22:10

Raghu