Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make the Jackson fail on converting double to int during deserialization

I use Jackson to deserialize a JSON to an immutable custom Java object. Here is the class:

final class DataPoint {
  private final int count;
  private final int median;

  @JsonCreator
  DataPoint(
      @JsonProperty("count") int count,
      @JsonProperty("median") int median) {
    if (count <= 0) {
      throw new IllegalArgumentException("...");
    }
    this.count = count;
    this.median = median;
  }

  // getters...
}

Here is the JSON I deserialize:

{
  "count": 1,
  "median": 2
}

It works fine. Now, I break the JSON, i.e. replace the integer median with the decimal:

{
  "count": 1,
  "median": 0.1
}

Now, I get count == 1, and median == 0. Instead, I would like the Jackson to fail deserilizing, since the data type of the JSON property median and the formal median parameter type (an int) are different, and the conversion looses the data actually.

Here is the deserializing code:

String json = "..."; // the second JSON
ObjectMapper mapper = new ObjectMapper()
    .enable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES)
    .enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
    .enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
DataPoint data = mapper.readValue(json, DataPoint.class);

Can I make Jackson fail when deserializing a decimal to an integer?

like image 955
danissimo Avatar asked Mar 09 '23 04:03

danissimo


2 Answers

There is the option ACCEPT_FLOAT_AS_INT for that purpose. E.g. :

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.ACCEPT_FLOAT_AS_INT);

And for "0.1" you will get:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not coerce a floating-point value ('0.1') into Integer; enable DeserializationFeature.ACCEPT_FLOAT_AS_INT to allow

You can see pertinent docs here

Note that this is available since Jackson 2.6

like image 106
Manos Nikolaidis Avatar answered Apr 08 '23 09:04

Manos Nikolaidis


You can define a JSON schema for your JSON document and run validation prior to deserialisation into the Java object.

If you define the median property as integer type, floating point number will be rejected.

This approach can also solve the problem about allowing float numbers that represent integers to be accepted too, for example 2.0. The schema needs to define the median property as follows:

{
  ...
  "median": { "type": "number", "multipleOf": 1.0 }
}
like image 39
RZet Avatar answered Apr 08 '23 09:04

RZet