简体   繁体   English

Java 9 javax.money.MonetaryAmount(JSR 354):无法将Pojo转换为XML,反之亦然

[英]Java 9 javax.money.MonetaryAmount (JSR 354): Unable to convert Pojo to XML and vice versa

I'm using Rest Api call to convert Pojo to XML. 我正在使用Rest Api调用将Pojo转换为XML。

Below is my code snippet: 以下是我的代码段:

TestAccount.java 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 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;
    }
}

when running the url on browser 在浏览器上运行网址时

http://localhost:8080/api/javaTest http:// localhost:8080 / api / javaTest

output: 输出:

<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>

As you can see When setting 如您所见,设置时

od.setPaymentAmount(MoneyUtil.of(10.898)); od.setPaymentAmount(MoneyUtil.of(10.898));

I'm getting loss of precision in XML as 我越来越失去XML的精度,因为

<number>10.9</number>

Also what are those extra XML tags? 还有那些额外的XML标签?

This problem occurs only with MonetaryAmount field otherwise code is running properly. 仅对于MonetaryAmount字段会发生此问题,否则代码将正常运行。 So, What is the Correct way to convert MonetaryAmount field to Pojo to XML and vice versa without losing precision. 因此,在不损失精度的情况下将MonetaryAmount字段转换为Pojo并转换为XML的正确方法是什么?

Could you share the code of your MoneyUtil/MoneyUtilityCls class? 您可以共享MoneyUtil / MoneyUtilityCls类的代码吗?

I am guessing the implementation of MonetaryAmount used is RoundedMoney with a default fraction digits of 1, which would lead to the described behaviour. 我猜想MonetaryAmount的实现是RoundedMoney,默认分数为1,这将导致所描述的行为。

The solution in this case would be to make the Utility return another class(Money for example) or to change the number of fraction digits of the returned RoundedMoney object. 在这种情况下,解决方案是使实用程序返回另一个类(例如,Money)或更改返回的RoundedMoney对象的小数位数。

"Representing money as a double or float will probably look good at first as the software rounds off the tiny errors, but as you perform more additions, subtractions, multiplications and divisions on inexact numbers, you'll lose more and more precision as the errors add up. This makes floats and doubles inadequate for dealing with money, where perfect accuracy for multiples of base 10 powers is required." “用双精度或浮点数表示的货币一开始看起来不错,因为该软件会消除微小的误差,但是当您对不精确的数字执行更多的加,减,乘和除运算时,由于错误而导致的精度越来越高加起来。这使得浮点数和加倍数不足以应付金钱,在这种情况下,需要十进制乘以10的幂的完美精度。”

Finally Java has a standard way to work with Currency And Money! 最后,Java具有使用Currency和Money的标准方式!

JSR 354: Money and Currency API JSR 354:货币和货币API

JSR 354 provides an API for representing, transporting, and performing comprehensive calculations with Money and Currency. JSR 354提供了一个API,用于表示,传输和执行Money和Currency的综合计算。 You can download it from this link: 您可以从以下链接下载:

JSR 354: Money and Currency API Download JSR 354:货币和货币API下载

The specification consists of the following things: 该规范包括以下内容:

  1. An API for handling eg monetary amounts and currencies 用于处理例如金额和货币的API
  2. APIs to support interchangeable implementations 支持互换实现的API
  3. Factories for creating instances of the implementation classes 用于创建实现类实例的工厂
  4. Functionality for calculations, conversion and formatting of monetary amounts 金额计算,转换和格式化的功能
  5. Java API for working with Money and Currencies, which is planned to be included in Java 9. 计划将包含在Java 9中的用于Money和Currencies的Java API。
  6. All specification classes and interfaces are located in the javax.money.* package. 所有规范类和接口都位于javax.money。*包中。

Sample Examples of JSR 354: Money and Currency API: JSR 354的示例示例:货币和货币API:

An example of creating a MonetaryAmount and printing it to the console looks like this:: 创建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));

When using the reference implementation API, the necessary code is much simpler: 使用参考实现API时,所需的代码要简单得多:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));

The API also supports calculations with MonetaryAmounts: 该API还支持MonetaryAmounts的计算:

MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));

CurrencyUnit and MonetaryAmount 货币单位和货币金额

// getting CurrencyUnits by locale
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);

MonetaryAmount has various methods that allow accessing the assigned currency, the numeric amount, its precision and more: 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 can be rounded using a rounding operator: 可以使用舍入运算符舍入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

When working with collections of MonetaryAmounts, some nice utility methods for filtering, sorting and grouping are available. 当使用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"));

Custom MonetaryAmount operations 自定义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

Resources: 资源:

Handling money and currencies in Java with JSR 354 使用JSR 354在Java中处理货币和货币

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

See Also: JSR 354 - Currency and Money 另请参见: JSR 354-货币和货币

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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