2016-07-15 127 views
1

我正在使用Rest Api调用将Pojo转换为XML。Java 9 javax.money.MonetaryAmount(JSR 354):无法将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,反之亦然,而不会损失精度。

回答

2

你能分享你的MoneyUtil/MoneyUtilityCls类的代码吗?

我猜测所使用的MonetaryAmount的实现是RoundedMoney,其默认分数位数为1,这会导致所描述的行为。

在这种情况下,解决方案将使实用程序返回另一个类(例如Money)或更改返回的RoundedMoney对象的小数位数。

+0

“在这种情况下,解决方案将使实用程序返回另一个类(例如Money)或更改返回的RoundedMoney对象的小数位数。”有效。谢谢。 – AftabLib

2

“将货币表示为double或float可能会首先看起来不错,因为软件会消除这些微小的错误,但是当您对不精确的数字执行更多的加法,减法,乘法和除法操作时,您将失去越来越多精度会随着错误的增加而增加,这使得花花公子和双花花公司不适合处理金钱,因为它需要完美的精度来满足10个基数的倍数要求。“

最后,Java有一个使用货币和金钱的标准方法!

JSR 354:金钱和货币API

JSR 354为代表,运输,并执行与金钱和货币全面计算的API。你可以从这个链接下载:

JSR 354: Money and Currency API Download

该规范由以下几件事:

  1. 处理E中的API。 G。货币量和货币
  2. API来支持互换实现
  3. 工厂创建的实现类的实例
  4. 功能为货币金额计算,转换和格式化
  5. 的Java API与金钱和货币,这是工作计划包含在Java 9中。
  6. 所有规范类和接口都位于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

Looking into the Java 9 Money and Currency API (JSR 354)

另请参见:JSR 354 - Currency and Money

相关问题