Java для Jackson JSON Сериализация: денежные поля
В настоящее время я использую Jackson для отправки результатов JSON из моего веб-приложения на основе Spring.
Проблема, с которой я сталкиваюсь, заключается в том, чтобы получить все денежные поля для вывода с двумя десятичными знаками. Я не смог решить эту проблему, используя setScale (2), поскольку числа, подобные 25.50, усекаются до 25,5 и т.д.
Кто-нибудь еще справился с этой проблемой? Я думал о создании класса Money с помощью пользовательского сериализатора Jackson... можете ли вы создать собственный сериализатор для переменной поля? Вероятно, вы можете... Но даже еще, как я могу заставить свой сериализатор клиентов добавить число в виде числа с двумя десятичными знаками?
Ответы
Ответ 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 и даже были некоторые обсуждения уже о том, как интегрировать его в официальную экосистему Джексона.