Need Jackson serializer for Double and need to specify precision at runtime

Viewed 18465

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 on the units or other criteria.

For example, spatial coordinates might be constrained to 5 or 6 digits after the decimal point, and temperature might be constrained to 2 digits after the decimal point. Default serializer behavior that has too many digits or truncated exponential notation is not good. What I need is something like:

@JsonSerialize(using=MyDoubleSerializer.class, precision=6) double myValue;

and better yet be able to specify the precision at run-time. I am also using a MixIn. I could write a serializer for each class but hoped to specify on specific values.

Any ideas would be appreciated.

3 Answers

After my initial more complex attempt, I found a simpler solution that works well. This involves using BigDecimal where appropriate only for output formatting. For example, the following code has getValueFormatted method that formats the value to the correct number of digits. In this case, the output JSON uses a short element name v rather than value and @JsonProperty("v") is used to indicate that the getValueFormatted method should be used to return the value for output. I did not put in a MixIn but could do that. This adds a method to the normal object but that is OK for REST service code.

  /**
   * Return the data value.
   * Ignored for JSON output because use getValueFormatted instead.
   */
  @JsonIgnore
  public Double getValue () {
    return this.value;
  }

  /**
   * Return the value formatted to appropriate number of digits.
   * This is used with serialization to output.
   * Use for JSON output because it is formatted to the correct number of digits.
   * @return the data value formatted to the appropriate number of digits.
   */
  @JsonProperty("v")
  public BigDecimal getValueFormatted () {
    // BigDecimal does not handle the concept of NaN and therefore can't serialize those values as Double does.
    if ( (this.value == null) || this.value.isNaN() || this.value.isInfinite() ) {
      return null;
    }
    BigDecimal bd = new BigDecimal(this.value).setScale(this.valueDigits,RoundingMode.HALF_UP);
    return bd;
  }
Related