There are many posts about creating Jackson serializers for numbers, currency, etc. For engineering applications, there is often a need to set the precision on numbers based
You may use Jackson's ContextualSerializer
to achieve desired serialization as shown below.
Firstly, create an annotation to capture precision
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Precision {
int precision();
}
Next, create a contextual serializer for Double
type which looks for Precision
annotation on the field to be serialized and then create a new serializer for the specified precision.
public class DoubleContextualSerializer extends JsonSerializer implements ContextualSerializer {
private int precision = 0;
public DoubleContextualSerializer (int precision) {
this.precision = precision;
}
public DoubleContextualSerializer () {
}
@Override
public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
if (precision == 0) {
gen.writeNumber(value.doubleValue());
} else {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(precision, RoundingMode.HALF_UP);
gen.writeNumber(bd.doubleValue());
}
}
@Override
public JsonSerializer> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
Precision precision = property.getAnnotation(Precision.class);
if (precision != null) {
return new DoubleContextualSerializer (precision.precision());
}
return this;
}
}
Finally, annotate your field to use custom serializer and set precision
public class Bean{
@JsonSerialize(using = DoubleContextualSerializer .class)
@Precision(precision = 2)
private double doubleNumber;
}
Hope this helps!!