[英]Java 9 javax.money.MonetaryAmount (JSR 354): Unable to convert Pojo to XML and vice versa
我正在使用Rest Api調用將Pojo轉換為XML。
以下是我的代碼段:
TestAccount.java
import javax.money.MonetaryAmount;
public class TestAccount {
private MonetaryAmount paymentAmount;
private String accountNumber;
public String getAccountNumber() {
return this.accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public MonetaryAmount getPaymentAmount() {
return this.paymentAmount;
}
public void setPaymentAmount(MonetaryAmount paymentAmount) {
this.paymentAmount = paymentAmount;
}
}
Controller.java
public class Controller extends BaseController {
@RequestMapping(value = "/javaTest", method = RequestMethod.GET, produces = { "application/xml" })
public TestAccount testMoneyPackage() {
TestAccount obj = new TestAccount();
obj.setAccountNumber("101423");
obj.setPaymentAmount(MoneyUtilityCls.of(10.898));
return obj;
}
}
在瀏覽器上運行網址時
http:// localhost:8080 / api / javaTest
輸出:
<OverdueAccount>
<accountNumber>101423</accountNumber>
<paymentAmount>
<currency>
<context>
<providerName>java.util.Currency</providerName>
<empty>false</empty>
</context>
<defaultFractionDigits>2</defaultFractionDigits>
<currencyCode>USD</currencyCode>
<numericCode>840</numericCode>
</currency>
<number>10.9</number>*****loss of precision*******
<negative>false</negative>
<zero>false</zero>
<precision>3</precision>
<scale>1</scale>
<positiveOrZero>true</positiveOrZero>
<positive>true</positive>
<negativeOrZero>false</negativeOrZero>
<factory>
<defaultMonetaryContext>
<precision>0</precision>
<amountType>org.javamoney.moneta.RoundedMoney</amountType>
<fixedScale>false</fixedScale>
<maxScale>-1</maxScale>
<providerName/>
<empty>false</empty>
</defaultMonetaryContext>
<amountType>org.javamoney.moneta.RoundedMoney</amountType>
<maxNumber/>
<minNumber/>
<maximalMonetaryContext>
<precision>0</precision>
<amountType>org.javamoney.moneta.RoundedMoney</amountType>
<fixedScale>false</fixedScale>
<maxScale>-1</maxScale>
<providerName/>
<empty>false</empty>
</maximalMonetaryContext>
</factory>
<context>
<precision>0</precision>
<amountType>org.javamoney.moneta.RoundedMoney</amountType>
<fixedScale>false</fixedScale>
<maxScale>-1</maxScale>
<providerName/>
<empty>false</empty>
</context>
</paymentAmount>
</OverdueAccount>
如您所見,設置時
od.setPaymentAmount(MoneyUtil.of(10.898));
我越來越失去XML的精度,因為
<number>10.9</number>
還有那些額外的XML標簽?
僅對於MonetaryAmount字段會發生此問題,否則代碼將正常運行。 因此,在不損失精度的情況下將MonetaryAmount字段轉換為Pojo並轉換為XML的正確方法是什么?
您可以共享MoneyUtil / MoneyUtilityCls類的代碼嗎?
我猜想MonetaryAmount的實現是RoundedMoney,默認分數為1,這將導致所描述的行為。
在這種情況下,解決方案是使實用程序返回另一個類(例如,Money)或更改返回的RoundedMoney對象的小數位數。
“用雙精度或浮點數表示的貨幣一開始看起來不錯,因為該軟件會消除微小的誤差,但是當您對不精確的數字執行更多的加,減,乘和除運算時,由於錯誤而導致的精度越來越高加起來。這使得浮點數和加倍數不足以應付金錢,在這種情況下,需要十進制乘以10的冪的完美精度。”
最后,Java具有使用Currency和Money的標准方式!
JSR 354:貨幣和貨幣API
JSR 354提供了一個API,用於表示,傳輸和執行Money和Currency的綜合計算。 您可以從以下鏈接下載:
該規范包括以下內容:
- 用於處理例如金額和貨幣的API
- 支持互換實現的API
- 用於創建實現類實例的工廠
- 金額計算,轉換和格式化的功能
- 計划將包含在Java 9中的用於Money和Currencies的Java API。
- 所有規范類和接口都位於javax.money。*包中。
JSR 354的示例示例:貨幣和貨幣API:
創建MonetaryAmount並將其打印到控制台的示例如下:
MonetaryAmountFactory<?> amountFactory = Monetary.getDefaultAmountFactory();
MonetaryAmount monetaryAmount = amountFactory.setCurrency(Monetary.getCurrency("EUR")).setNumber(12345.67).create();
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));
使用參考實現API時,所需的代碼要簡單得多:
MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));
該API還支持MonetaryAmounts的計算:
MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));
貨幣單位和貨幣金額
// getting CurrencyUnits by locale
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);
MonetaryAmount具有多種方法,可用於訪問分配的貨幣,數字量,其精度等:
MonetaryAmount monetaryAmount = Money.of(123.45, euro);
CurrencyUnit currency = monetaryAmount.getCurrency();
NumberValue numberValue = monetaryAmount.getNumber();
int intValue = numberValue.intValue(); // 123
double doubleValue = numberValue.doubleValue(); // 123.45
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45
int precision = numberValue.getPrecision(); // 5
// NumberValue extends java.lang.Number.
// So we assign numberValue to a variable of type Number
Number number = numberValue;
可以使用舍入運算符舍入MonetaryAmount:
CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");
MonetaryAmount dollars = Money.of(12.34567, usd);
MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);
MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35
當使用MonetaryAmounts的集合時,可以使用一些不錯的實用程序方法進行過濾,排序和分組。
List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(2, "EUR"));
amounts.add(Money.of(42, "USD"));
amounts.add(Money.of(7, "USD"));
amounts.add(Money.of(13.37, "JPY"));
amounts.add(Money.of(18, "USD"));
自定義MonetaryAmount操作
// A monetary operator that returns 10% of the input MonetaryAmount
// Implemented using Java 8 Lambdas
MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {
BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);
BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));
return Money.of(tenPercent, amount.getCurrency());
};
MonetaryAmount dollars = Money.of(12.34567, "USD");
// apply tenPercentOperator to MonetaryAmount
MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567
資源:
研究Java 9 Money and Currency API(JSR 354)
另請參見: JSR 354-貨幣和貨幣
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.