Martin Schröder
Martin Schröder

Reputation: 4591

Format a float as fixed point with Jackson

I've searched the Jackson docs, but can't find any good documentation for the pattern of @JsonFormat for floating point numbers.

Given a field

@JsonProperty("Cost")
private Double cost;

How can I get Jackson to format it as fixed point number with four digits precision in decimal format with @JsonFormat?

PS: I know one should not use floats for money. Spare us the discussion, please.

Upvotes: 0

Views: 9415

Answers (3)

Utku A.
Utku A.

Reputation: 858

You can specify your own formatter in custom serializer class.

    formatter = new DecimalFormat();
    formatter.setMaximumFractionDigits(2);
    formatter.setMinimumFractionDigits(2);
    formatter.setGroupingUsed(false);
    DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance();
    sym.setDecimalSeparator('.');
    formatter.setDecimalFormatSymbols(sym);

Then, in actual serialize method:

    final String output = formatter.format(value);
    jsonGenerator.writeNumber(output);

Upvotes: 3

Martin Schröder
Martin Schröder

Reputation: 4591

Building on @Veselin's answers I'm using

public class DoubleDecimalSerializerWithSixDigitPrecisionAndDotSeparator
    extends JsonSerializer<Double> {

  @Override
  public void serialize(Double value, JsonGenerator generator, SerializerProvider serializers)
      throws IOException {
    generator.writeNumber(String.format(Locale.US, "%.6f", value));
  }
}

The use case is the generation of CSVs in Germany, so I don't care for JSON formatting and want a "." as a decimal separator.

Upvotes: 2

Veselin Davidov
Veselin Davidov

Reputation: 7081

You would need to create a custom Serializer for that. Something like

 @JsonProperty("amountOfMoney")
 @JsonSerialize(using = MySerializer.class)
 private Double cost;

 public class MySerializerextends JsonSerializer<Double> {
    @Override
    public void serialize(Double value, JsonGenerator generator, SerializerProvider provider) throws IOException,
            JsonProcessingException {  
        double roundedValue = value*10000;
        roundedValue = Math.round(roundedValue );
        roundedValue = roundedValue /10000;          
        generator.writeNumber(roundedValue );
    }
 }

You can see about the class here https://fasterxml.github.io/jackson-databind/javadoc/2.3.0/com/fasterxml/jackson/databind/JsonSerializer.html

The rounding part might not be the best. You can do it as you prefer ;) Using decimal format can work too. If you use writeNumber it will print the value as a number in the result Json. That's why I changed my answer from writeString and using decimal format.

You should be able to use pattern of @JsonFormat for that if the implementation allows it.

Datatype-specific additional piece of configuration that may be used to further refine formatting aspects. This may, for example, determine low-level format String used for Date serialization; however, exact use is determined by specific JsonSerializer

But with jackson I believe it works only for dates.

Upvotes: 2

Related Questions