Issue
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?
Solution
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);
}
}
Answered By - İsmail Y.
Answer Checked By - David Goodson (JavaFixing Volunteer)