MoneyFormatter::parseMoney создает исключение MoneyFormatException

Возьмите этот SSCCE (с установленной библиотекой Joda-Money):

public static void main(String[] args) {
    BigDecimal bd = new BigDecimal("100");
    MoneyFormatter mf = new MoneyFormatterBuilder().appendLiteral("$ ").appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING).toFormatter();
    String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); // The MoneyFormatter is what printed this string...
    System.out.println(money_as_string);
    Money money = mf.parseMoney(money_as_string); // You think it should be able to parse the string it gave me, right?
}

Я использовал MoneyFormatter распечатать String: money_as_string, Мое (разумное?) Ожидание состояло в том, что я мог использовать то же самое MoneyFormatter разобрать строку обратно в Money объект. Но, увы, без игры в кости. Выдает эту ошибку:

Exception in thread "main" org.joda.money.format.MoneyFormatException: Parsing did not find both currency and amount: $ 100.00
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:237)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at test4.Test12.main(Test12.java:35)

Итак, мой вопрос: как именно получить Money объект из String?

РЕДАКТИРОВАТЬ: @durron597, ваша информация была полезной, но не ответил на вопрос. Как именно вы идете от String к Money объект тогда?

Я добавил код для удаления знака доллара:

public static void main(String[] args) {
    BigDecimal bd = new BigDecimal("100");
    MoneyFormatter mf = new MoneyFormatterBuilder().appendLiteral("$ ").appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING).toFormatter();
    String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); // The MoneyFormatter is what printed this string...
    System.out.println(money_as_string);
    Money money = mf.parseMoney(money_as_string.replace("$", "").trim()); // You think it should be able to parse the string it gave me, right?
}

и я получил это:

Exception in thread "main" org.joda.money.format.MoneyFormatException: Text could not be parsed at index 0: 100.00
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:233)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at test4.Test12.main(Test12.java:35)

Таким образом, он не может анализировать текст с или без символа валюты.

Может ли кто-нибудь получить parseMoney() функционировать, когда-либо??

1 ответ

Решение

Итак, первое, что выделилось мне, это то, что вы использовали appendLiteral и не appendCurrencySymbolLocalized (что если вы используете CurrencyUnit.EUR? Вы не хотели бы $).

Однако, когда вы измените это на это:

MoneyFormatter mf = new MoneyFormatterBuilder()
        .appendCurrencySymbolLocalized()
        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
        .toFormatter();

Вместо этого ваш код выдает это исключение:

Exception in thread "main" java.lang.UnsupportedOperationException: MoneyFomatter has not been configured to be able to parse
    at org.joda.money.format.MoneyFormatter.parse(MoneyFormatter.java:281)
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:229)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at MoneyTest.main(MoneyTest.java:17)

Дальнейшее изучение выявляет эту красноречивую черту в javadoc:

appendCurrencySymbolLocalized

publicMoneyFormatterBuilderappendCurrencySymbolLocalized()

Добавляет локализованный символ валюты к строителю. Локализованный символ валюты - это символ, выбранный языком форматера.

Символы не могут быть проанализированы.

Возвращает: это для цепочки, никогда не нуль

Почему это может быть? Возможно потому, что символы валют неоднозначны. Многие страны используют доллар. Вот несколько примеров:

В дополнение к тем странам мира, которые используют доллары или песо, ряд других стран используют символ $ для обозначения своих валют, в том числе:

  • Никарагуанская Кордова (обычно пишется как C $)
  • Samoan tālā (транслитерация слова доллар)
  • Тонганская паанга
  • Зимбабве (обычно пишется как Z$)

Попробуйте этот код:

MoneyFormatter mf = new MoneyFormatterBuilder()
        .appendCurrencyCode()
        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
        .toFormatter();

Это сделает что-то вроде USD 100.00 печать, которая будет проанализирована правильно. Если у вас обязательно должен быть символ доллара, вам понадобится реализовать свой собственный принтер / парсер. Или вы можете использовать это:

import java.io.IOException;
import java.math.BigDecimal;

import org.joda.money.BigMoney;
import org.joda.money.CurrencyUnit;
import org.joda.money.IllegalCurrencyException;
import org.joda.money.Money;
import org.joda.money.format.MoneyAmountStyle;
import org.joda.money.format.MoneyFormatter;
import org.joda.money.format.MoneyFormatterBuilder;
import org.joda.money.format.MoneyParseContext;
import org.joda.money.format.MoneyParser;
import org.joda.money.format.MoneyPrintContext;
import org.joda.money.format.MoneyPrinter;

public class MoneyTest {
    private static enum DollarParserPrinter implements MoneyParser,
            MoneyPrinter {
        INSTANCE;

        private static final String DOLLAR_SYMBOL = "$ ";

        @Override
        public void parse(MoneyParseContext context) {
            int endPos = context.getIndex() + 2;
            if (endPos > context.getTextLength()) {
                context.setError();
            } else {
                String code =
                        context.getTextSubstring(context.getIndex(), endPos);
                if(DOLLAR_SYMBOL.equals(code)) {
                    context.setCurrency(CurrencyUnit.USD);
                    context.setIndex(endPos);
                }
            }
        }

        @Override
        public void print(MoneyPrintContext context, Appendable appendable,
                BigMoney money) throws IOException {
            if(CurrencyUnit.USD == money.getCurrencyUnit()) {
                appendable.append(DOLLAR_SYMBOL);
            } else {
                throw new IllegalCurrencyException("This parser only knows how to print US Dollar money!");
            }
        }
    }

    public static void main(String[] args) {
        BigDecimal bd = new BigDecimal("100");
        MoneyFormatter mf =
                new MoneyFormatterBuilder().append(DollarParserPrinter.INSTANCE, DollarParserPrinter.INSTANCE)
                        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
                        .toFormatter();
        String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); 
        System.out.println(money_as_string);
        Money money = mf.parseMoney(money_as_string);
        System.out.println(money);
    }
}
Другие вопросы по тегам