Search code examples
javajsonjackson

How can I recognise undeclared primitives with Jackson?


I have the following Jackson class:

public class InspectArrayFormulaArgs {

    private final int expectedColumns;

    @JsonCreator
    public InspectArrayFormulaArgs(@JsonProperty(value = "expectedColumns", defaultValue = "-1") int expectedColumns) {
        this.expectedColumns = expectedColumns;
    }

}

I would expect Jackson to check whether the parsed Json contains the field expectedColumns, and:

  • If the field is there, take it as is
  • Else, use the defaultValue that I declared

However, the value parsed by Jackson is still 0 when this pojo is parsed.

I've thought it may be due to the fact that the JDK initialises an int as 0 and Jackson doesn't understand the field is not in the Json (even though I thought they were parsing the Json directly).

So I've tried to use Integer instead of int as a parameter for the constructor, but this ends up into a NullPointerException because Jackson doesn't assign the value -1 and so the JDK tries an unboxing of null into the field int expectedColumns.

Any idea on how I should do this?

Notes:

  1. I've tried annotating the class with @JsonInclude(JsonInclude.Include.NON_DEFAULT) but it didn't change anything
  2. I assume I may declare the field as being an Integer instead of int, but Jackson still leaves it as null (doesn't assign -1) and I wanted to avoid doing checks on my side such as value != null ? value : -1. Of course I'll do that if no solution, but I find it strange that Jackson is uncapable to understand what I'm asking so I'm wondering whether it's me asking it the wrong way

Solution

  • The defaultValue element is for documentation purposes only. It has no practical effect.

    Property that may be used to document expected default value for the property: most often used as source information for generating schemas (like JSON Schema or protobuf/thrift schema), or documentation. It may also be used by Jackson extension modules; core jackson-databind does not have any automated handling beyond simply exposing this value through bean property introspection.

    You could provide a different default value by overriding getNullValue in a custom deserialiser.

    @JsonCreator
    public InspectArrayFormulaArgs(
            @JsonDeserialize(using = DefaultMinusOneDeserializer.class)
            @JsonProperty(value = "expectedColumns", defaultValue = "-1")
            int expectedColumns
    ) {
        this.expectedColumns = expectedColumns;
    }
    
    static class DefaultMinusOneDeserializer extends JsonDeserializer<Integer> {
        @Override
        public Integer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            return jsonParser.getIntValue();
        }
    
        @Override
        public Integer getNullValue(DeserializationContext ctxt) {
            return -1;
        }
    }