Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force spring boot jackson deserializer to use BigDecimal

I'm having a problem in which jackson is deserializing numeric values into arbitrary types which I cannot predict. For example, if someone passes the value "14", jackson will instantiate it as an Integer. However, if someone passes the value "14.01" then jackson will instantiate it as a Double. This is a problem because I have a custom deserializer (@JsonCreator) which is throwing exceptions since I cannot predictable cast the field into a BigDecimal. Ideally jackson would just turn everything into a BigDecimal.

I found a post which suggests that Jackson might be capable of doing something like this. Deserialize JSON into a generic map, forcing all JSON floats into Decimal or String, in Jackson

However, I can't figure out how to access the mapper object hidden inside Spring Boot in order to run the appropriate method mapper.enable().

Here is a snippet of the deserializer:

@JsonCreator
public OptionTransaction(Map<String,Object> jsonObj){  
    Map<String,Object> jsonOption = (Map<String, Object>) jsonObj.get("option");

    Map<String,Object> optionPriceObj = (Map<String, Object>) jsonOption.get("price");
    BigDecimal optionValue = new BigDecimal((Double) optionPriceObj.get("value"));

As you can see above, that Double cast is a problem because jackson is sometimes not feeding in doubles. Does anyone know an easy way to get jackson to either always output BigDecimals, or even just strings?

UPDATE:

As far as getting doubles converted to BigDecimal, I accomplished this by modifying application.properties in the following way:

# ===============================
# = DESERIALIZATION CUSTOMIZATION
# ===============================
spring.jackson.deserialization.USE_BIG_DECIMAL_FOR_FLOATS=true
like image 222
melchoir55 Avatar asked Oct 24 '16 08:10

melchoir55


1 Answers

@JsonCreator
public OptionTransaction(Map<String,Object> jsonObj){  
    Map<String,Object> jsonOption = (Map<String, Object>) jsonObj.get("option");

    Map<String,Object> optionPriceObj = (Map<String, Object>) jsonOption.get("price");
    BigDecimal optionValue = new BigDecimal((Double) optionPriceObj.get("value"));
}

..

ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);

OptionTransaction transaction = mapper.readValue(jsonString, OptionTransaction.class);

https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features

like image 63
kuhajeyan Avatar answered Nov 09 '22 17:11

kuhajeyan