I'm using an external library in my project. One of it's models has a BigDecimal property, that requires a custom precision. If this model was mine, i would apply a @JsonSerialize annotation that uses custom serializer. But i can't modify sources of ext. lib... Is there any way to apply it somehow?
Exactly for this use-case Jackson offers so-called mixins. To illustrate how to use this let's walk through an example:
Suppose you have a library class (named Model
) containing
a property of type BigDecimal
.`
public class Model {
private BigDecimal number;
public BigDecimal getNumber() {
return number;
}
public void setNumber(BigDecimal number) {
this.number = number;
}
}
Now, you cannot modify the source of the library class above.
But instead, you can write a class (let's call it ModelMixin
)
which kind of mirrors the library class Model
and
put any Jackson annotations there.
Especially you can specify your own serializer for
the BigDecimal number
property.
public abstract class ModelMixin {
@JsonSerialize(using = MyBigDecimalSerializer.class)
private BigDecimal number;
}
The serializer might be as simple or sophisticated
as you need it. Here is a simple one which
chooses to write the BigDecimal
as a JSON string.
public class MyBigDecimalSerializer extends JsonSerializer<BigDecimal> {
@Override
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.toString());
}
}
Now you need to tell Jackson's ObjectMapper
to take the annotations from the ModelMixin
class
and apply them to theModel
class.
This is done by the addMixIn(Class,Class)
method.
ObjectMapper objectMapper = new ObjectMapper()
.addMixIn(Model.class, ModelMixin.class);
Model model = new Model();
model.setNumber(BigDecimal.valueOf(123.456));
objectMapper.writeValue(System.out, model);
This writes the following JSON output:
{"number":"123.456"}