我使用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的正确方法是什么,反之亦然,而不会失去精度。
答案 0 :(得分:2)
你能分享你的MoneyUtil / MoneyUtilityCls类的代码吗?
我猜测使用MonetaryAmount的实现是RoundedMoney,默认小数位数为1,这将导致所描述的行为。
这种情况下的解决方案是让Utility返回另一个类(例如Money)或更改返回的RoundedMoney对象的小数位数。
答案 1 :(得分:1)
“代表金钱作为双倍或浮动可能一开始看起来很好,因为软件会对微小的错误进行补偿,但是当您对不精确的数字执行更多的加法,减法,乘法和除法时,您将失去越来越多的精度因为错误加起来。这使浮动和双打不足以处理金钱,其中需要基本10倍数倍的完美准确度。“
最后,Java有一种标准的方式来处理货币和货币!
JSR 354:货币和货币API
JSR 354提供了一个API,用于使用货币和货币表示,传输和执行综合计算。您可以从以下链接下载:
JSR 354: Money and Currency API Download
该规范包含以下内容:
- 用于处理e的API。 G。货币金额和货币
- 支持可互换实施的API
- 用于创建实施类实例的工厂
- 货币金额的计算,转换和格式化功能
- 用于处理货币和货币的Java API,计划包含在Java 9中。
- 所有规范类和接口都位于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"));
CurrencyUnit和MonetaryAmount
// 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;
MonetaryAmounts可以使用舍入运算符进行舍入:
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
资源:
Handling money and currencies in Java with JSR 354