简体   繁体   中英

BigDecimal: Issue with zero as last decimal

I have a Spring Boot application consuming a rest api delivering some decimal values for example:

"Amount": {
  "Amount": 160.10,
  "Currency": "EUR"
}

I map this to BigDecimal which is giving me issues. I need the last decimal, even if it is zero, because I need the amount with no decimals, ie using BigDecimal.unscaledValue()

For the shown data I would expect the output of x.getAmount().unscaledValue() to be "16010" but since the value is internally represented as 160.1 (non-significant 0 is stripped) I get "1601" which is a factor of 10 off, when some code further down the line divides by 10.

The value can have either 0, 2 or 3 decimal places (depending on the currency).

My first thought was to use the setScale() method, but that brought me no luck.

Java 11 code to parse json:


restTemplate 
  .exchange(request, new ParameterizedTypeReference<List<NotificationMessage>>() {})
  .getBody()

model:

import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import java.math.BigDecimal;

import lombok.Data;

@Data
@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
public class TransactionAmount {
//  @JsonRawValue //my test to force it
    private BigDecimal amount;

    private String currency;

}

Is there a way I can force Spring Boot to preserve the non-significant decimals?

(modifying the API to use strings instead is not an option)

Solution was simply to introduce a custom Jackson Mapper which parses the value as String instead of float :

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;

import java.math.BigDecimal;

@Data
@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
public class TransactionAmount {

    private BigDecimal amt;

    private String ccy;
    
    // Custom mapper to make sure we get the complete decimal value - by treating the amount as a String instead of a Float
    @JsonCreator
    public TransactionAmount1(
      @JsonProperty("Amt") String amount, 
      @JsonProperty("Ccy") String ccy) {
        this.amt = new BigDecimal(amount);
        this.ccy = ccy;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM