Quando desserializo um número JSON para um BigDecimal
usando readTree
, os resultados não preservam a escala, ou seja, são tratados 0.10
como 0.1
. Por outro lado, se eu desserializo usando readValue
, ele preserva a escala, retornando um BigDecimal
com a escala correta de 2:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
JsonNode jsonNode = objectMapper.readTree("0.10");
BigDecimal numberFromReadTree = ((DecimalNode)jsonNode).decimalValue();
BigDecimal numberFromReadValue = objectMapper.readValue("0.10", BigDecimal.class);
System.out.println(numberFromReadTree); // Prints 0.1, i.e. scale = 1
System.out.println(numberFromReadValue); // Prints 0.10, i.e. scale = 2
Existe algum motivo para essa aparente inconsistência e existe uma opção que eu possa definir para manter a escala igual à entrada (ou seja, para ser consistente com readValue
)?
Como você apontou, o motivo dessa inconsistência está em uma opção que pode ser definida para
JSonNode
os nós que serão criados:Basicamente, o
ObjectMapper
mapeador precisa definir seuJSonNodeFactory
atributo passando um novoJsonNodeFactory
objeto criado peloJsonNodeFactory#JsonNodeFactory-boolean
construtor usando otrue
valor que indica que instâncias de DecimalNode devem ser construídas com representações exatas de instâncias de BigDecimal, enquanto oObjectMapper
construtor std possui umJsonNodeFactory
objeto criado pelo construtor no-arg (e a instância padrão) com umfalse
valor padrão como argumento.No segundo caso que utiliza um
ObjectMapper
mapeador sem tocar noJSonNodeFactory
atributo:Funciona porque na
BigDecimal
classe oBigDecimal.html#BigDecimal-java.lang.String
construtor está presente e é usado diretamente peloObjectMapper
mapeador, dando o resultado esperado.