使用Moneta(JavaMoney)JSR354实现定制MonetaryMountFormat
对于如何使用Moneta JSR-354实现定制使用Moneta(JavaMoney)JSR354实现定制MonetaryMountFormat,java,jsr354,Java,Jsr354,对于如何使用Moneta JSR-354实现定制MonetaryMountFormat,我感到非常困惑 我的目的是能够将1.23和$3.45解析为MonetaryAmounts 下面是我的单元测试: @Test public void testString() { Bid bid = new Bid("1.23"); assertEquals(1.23, bid.getValue(), 0.0); System.out.println(bid); bid = n
MonetaryMountFormat
,我感到非常困惑
我的目的是能够将1.23
和$3.45
解析为MonetaryAmount
s
下面是我的单元测试:
@Test
public void testString() {
Bid bid = new Bid("1.23");
assertEquals(1.23, bid.getValue(), 0.0);
System.out.println(bid);
bid = new Bid("$3.45");
assertEquals(3.45, bid.getValue(), 0.0);
System.out.println(bid);
}
这是我的班级:
public final class Bid {
private static final CurrencyUnit USD = Monetary.getCurrency("USD");
private MonetaryAmount bid;
/**
* Constructor.
*
* @param bidStr the bid
*/
public Bid(String bidStr) {
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(Locale.US)
.set("pattern", "###.##")
.build());
if (StringUtils.isNotBlank(bidStr)) {
bidStr = bidStr.trim();
bidStr = bidStr.startsWith("$") ? bidStr.substring(1) : bidStr;
try {
bid = FastMoney.parse(bidStr, format);
} catch (NumberFormatException e) {
bid = FastMoney.of(0, USD);
}
}
}
/**
* Constructor.
*
* @param bidDouble the bid
*/
public Bid(double bidDouble) {
bid = FastMoney.of(bidDouble, USD);
}
public double getValue() {
return bid.getNumber().doubleValue();
}
}
我真的很想能够使用单一的
MonetaryAmountFormat
解析bidStr
,但在花了很多时间试图找出如何使$
可选之后,我放弃了。不幸的是,我甚至不知道如何将1.23
解析为USD。Moneta抛出一个NullPointerException
。我应该使用AmountFormatQueryBuilder设置货币吗?使用AmountFormatQueryBuilder可以设置的所有键是什么?我搜索了文档,但除了一些常用键之外,在任何地方都找不到任何文档,比如pattern
JavaMoney在试图解析非限定数字(比如1.23
)时似乎无法正常工作
默认情况下,MonetaryAmountFormat
希望您提供货币名称(如USD 1.23
):
如果设置了CurrencyStyle.SYMBOL
,则可以按货币名称或符号进行分析(因此,1.23美元或3.45美元
):
这可能是你用JavaMoney得到的最接近的结果
如果您知道您只从同一种货币中获取数字,那么最好在其他地方解析字符串(使用regex或其他东西),并转换为一致的输入格式,因为(正如您所发现的那样),当JavaMoney不满意时,您很容易获得NullPointerException
s而无需解释
就可用键而言,您可以查看org.javamoney.moneta.format.AmountFormatParams
:模式
,分组大小
,分组分离器
设置格式时,请务必注意,必须使用泛型:·
。例如,您可以执行.set(“pattern”、“·0.00”)
最后,您可以直接从MonetaryAmountFormat
解析,而不是直接使用Moneta RI中的FastMoney
类:
// rather than using Monata directly:
MonetaryAmount amount = FastMoney.parse(bidStr, format);
// use the API:
MonetaryAmount amount = format.parse(bidStr);
如果您使用的是自定义格式模式,那么您可以解析只包含一个没有货币的数字的字符串,但是您应该自己指定所需的货币。
以下是一个例子:
@Test
public void testParse_pattern_without_currency_sign_but_with_currency_in_context() {
CurrencyUnit usd = Monetary.getCurrency("USD");
AmountFormatContextBuilder builder = AmountFormatContextBuilder.of(US);
builder.set(AmountFormatParams.PATTERN, "0.00"); // the pattern doesn't contains a currency sign ¤
builder.set(CurrencyUnit.class, usd); // set expected currency
AmountFormatContext context = builder.build();
DefaultMonetaryAmountFormat format = new DefaultMonetaryAmountFormat(context);
MonetaryAmount parsedAmount = format.parse("0.01 USD");
assertSame(parsedAmount.getCurrency(), usd);
assertEquals(parsedAmount.getNumber().doubleValueExact(), 0.01D);
assertEquals(parsedAmount.toString(), "USD 0.01");
}
请注意,您需要使用set(CurrencyUnit.class,usd)
创建上下文
但是,如果您尝试使用货币符号设置模式,例如0.00·
,则会收到一个错误:javax.money.format.monetaryparseeException:错误解析CurrencyUnit:无输入
我为此创建了一张罚单,请阅读并添加您的意见
// rather than using Monata directly:
MonetaryAmount amount = FastMoney.parse(bidStr, format);
// use the API:
MonetaryAmount amount = format.parse(bidStr);
@Test
public void testParse_pattern_without_currency_sign_but_with_currency_in_context() {
CurrencyUnit usd = Monetary.getCurrency("USD");
AmountFormatContextBuilder builder = AmountFormatContextBuilder.of(US);
builder.set(AmountFormatParams.PATTERN, "0.00"); // the pattern doesn't contains a currency sign ¤
builder.set(CurrencyUnit.class, usd); // set expected currency
AmountFormatContext context = builder.build();
DefaultMonetaryAmountFormat format = new DefaultMonetaryAmountFormat(context);
MonetaryAmount parsedAmount = format.parse("0.01 USD");
assertSame(parsedAmount.getCurrency(), usd);
assertEquals(parsedAmount.getNumber().doubleValueExact(), 0.01D);
assertEquals(parsedAmount.toString(), "USD 0.01");
}