[英]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.