Подтвердить что ты не робот

Java для Jackson JSON Сериализация: денежные поля

В настоящее время я использую Jackson для отправки результатов JSON из моего веб-приложения на основе Spring.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы получить все денежные поля для вывода с двумя десятичными знаками. Я не смог решить эту проблему, используя setScale (2), поскольку числа, подобные 25.50, усекаются до 25,5 и т.д.

Кто-нибудь еще справился с этой проблемой? Я думал о создании класса Money с помощью пользовательского сериализатора Jackson... можете ли вы создать собственный сериализатор для переменной поля? Вероятно, вы можете... Но даже еще, как я могу заставить свой сериализатор клиентов добавить число в виде числа с двумя десятичными знаками?

4b9b3361

Ответ 1

У меня была такая же проблема, и я ее форматировал в JSON как String. Возможно, это будет немного взломать, но его легко реализовать.

private BigDecimal myValue = new BigDecimal("25.50");
...
public String getMyValue() {
    return myValue.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
}

Ответ 2

Вы можете использовать пользовательский сериализатор на своем денежном поле. Вот пример с MoneyBean. Сумма поля аннотируется с помощью @JsonSerialize (используя =...).

public class MoneyBean {
    //...

    @JsonProperty("amountOfMoney")
    @JsonSerialize(using = MoneySerializer.class)
    private BigDecimal amount;

    //getters/setters...
}

public class MoneySerializer extends JsonSerializer<BigDecimal> {
    @Override
    public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
            JsonProcessingException {
        // put your desired money style here
        jgen.writeString(value.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
    }
}

Что это. Теперь BigDecimal напечатан правильно. Я использовал простой тестовый файл, чтобы показать его:

@Test
public void jsonSerializationTest() throws Exception {
     MoneyBean m = new MoneyBean();
     m.setAmount(new BigDecimal("20.3"));

     ObjectMapper mapper = new ObjectMapper();
     assertEquals("{\"amountOfMoney\":\"20.30\"}", mapper.writeValueAsString(m));
}

Ответ 3

Вместо настройки @JsonSerialize для каждого члена или получателя вы можете настроить модуль, который использует сериализатор custome для определенного типа:

SimpleModule module = new SimpleModule();
module.addSerializer(BigInteger.class, new ToStringSerializer());
objectMapper.registerModule(module);

В приведенном выше примере я использовал сериализатор строк для сериализации BigIntegers (поскольку javascript не может обрабатывать такие числовые значения).

Ответ 4

Я один из сопровождающих jackson-datatype-money, поэтому возьмите этот ответ с солью, так как я, конечно, предвзятый. Модуль должен покрывать ваши потребности, и он довольно легкий (без дополнительных зависимостей времени исполнения). Кроме того, он упоминается в Jackson docs, Spring docs и даже были некоторые обсуждения уже о том, как интегрировать его в официальную экосистему Джексона.