Я использую собственный сериализатор / десериализатор для BigDecimals в JSON в моем приложении Spring Boot.Все значения типа float / double отображаются как BigDecimals, и сериализатор / десериализатор гарантирует, что масштаб BigDecimal составляет не менее 2.
В качестве примера у меня есть следующее в моем модульном тесте для создания ObjectMapper
private ObjectMapper getObjectMapper() {
Jackson2ObjectMapperBuilderCustomizer customizer =
jacksonObjectMapperBuilder -> {
jacksonObjectMapperBuilder.featuresToEnable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
jacksonObjectMapperBuilder.serializerByType(BigDecimal.class, new BigDecimalSerializer(BigDecimal.class));
jacksonObjectMapperBuilder.deserializerByType(BigDecimal.class, new BigDecimalDeserializer());
};
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
customizer.customize(builder);
ObjectMapper objectMapper = builder.build();
objectMapper.setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));
return objectMapper;
}
Затем у меня будет следующий модульный тест:
@Test
public void testCustomOM() {
ObjectMapper om = getObjectMapper();
ObjectNode rootNode = om.createObjectNode();
rootNode.put("balance", new BigDecimal(37D));
BigDecimal fromBigDecimal = om.convertValue(rootNode.get("balance"), BigDecimal.class);
Map map = om.convertValue(rootNode, Map.class);
BigDecimal fromMap = (BigDecimal) map.get("balance");
assertEquals(2, fromBigDecimal.scale()); // Success
assertEquals(2, fromMap.scale()); // Assert fails
}
Сериализатор BigDecimal
public class BigDecimalSerializer extends StdSerializer<BigDecimal> {
public BigDecimalSerializer(Class<BigDecimal> t) {
super(t);
}
@Override
public void serialize(BigDecimal bigDecimal, JsonGenerator generator, SerializerProvider provider) throws IOException {
generator.writeNumber(setScale(bigDecimal));
}
private BigDecimal setScale(BigDecimal bigDecimal) {
if (bigDecimal.scale() < 2) {
return bigDecimal.setScale(2, RoundingMode.HALF_EVEN);
}
return bigDecimal;
}
}
И BigDecimalDeserializer
public class BigDecimalDeserializer extends NumberDeserializers.BigDecimalDeserializer {
@Override
public BigDecimal deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return setScale(super.deserialize(parser, context));
}
private BigDecimal setScale(BigDecimal bigDecimal) {
if (bigDecimal.scale() < 2) {
return bigDecimal.setScale(2, RoundingMode.HALF_EVEN);
}
return bigDecimal;
}
}
Когда я запускаютест, BigDecimal, который я получаю от преобразования JsonNode, имеет масштаб два, но один, который я получаю из карты, равен 0. Так что, похоже, он не использует BigDecimalDeserializer, который я определил при преобразовании в карту.
Есть ли способ заставить Джексона последовательно использовать этот десериализатор?