ObjectMapper непоследовательно отображает BigDecimal - PullRequest
0 голосов
/ 02 января 2019

Я использую собственный сериализатор / десериализатор для 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, который я определил при преобразовании в карту.

Есть ли способ заставить Джексона последовательно использовать этот десериализатор?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...