Home > Mobile >  Default method in Jackson MixIn interface doesn't work
Default method in Jackson MixIn interface doesn't work

Time:08-02

I'm using a bean of which I don't control the source, say: TheirClass:

public class TheirClass {

    private String property;
}

I want to a timestamp to every TheirClass instance I serialize using a MixIn:

public interface TheirClassMixIn {

    @JsonProperty
    default long getTimestamp() {
        return System.currentTimeMillis();
    }

}

and I let Spring know about it:

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer someCustomizer() {
        return builder -> builder
                .mixIn(TheirClass.class, TheirClassMixIn.class);
    }

but this doesn't seem to work. What am I missing and how can I achieve putting a fixed extra property to every TheirClass instance?

CodePudding user response:

You can't do this just by adding property to mix-in class/interface because "Mix-in" annotations are a way to associate annotations with classes, without modifying (target) classes themselves, originally intended to help support 3rd party datatypes where user can not modify sources to add annotations.

You can use it by adding @JsonAppend to your mix-in interface, this annotation is used to add virtual properties to an object in addition to regular ones when that object is serialized.

It can be used with the mix-in functionality to avoid modifying the original POJO.

Let’s rewrite your example:

@JsonAppend(
    props = {
            @JsonAppend.Prop(
                    name = "timestamp", type = Long.class,
                    value = TimestampPropertyWriter.class)
    }
)
public interface TheirClassMixIn {}

To complete this story I’ll show an implementation of TimestampPropertyWriter. It’s just a class that knows how to evaluate the value of our “virtual” property given an instance of TheirClass:

public class TimestampPropertyWriter extends VirtualBeanPropertyWriter {

    public TimestampPropertyWriter() {
    }

    public TimestampPropertyWriter(BeanPropertyDefinition propDef,
                                   Annotations contextAnnotations,
                                   JavaType declaredType) {
        super(propDef, contextAnnotations, declaredType);
    }

    @Override
    protected Object value(Object bean,
                           JsonGenerator gen,
                           SerializerProvider prov) {
        return System.currentTimeMillis();
    }

    @Override
    public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config,
                                                AnnotatedClass declaringClass,
                                                BeanPropertyDefinition propDef,
                                                JavaType type) {
        return new TimestampPropertyWriter(propDef, declaringClass.getAnnotations(), type);
    }
}
  • Related