Search code examples
javajsonjacksondeserializationjson-deserialization

An empty JSON field which is a boolean/nullable field in Java model, is getting converted as null


I have a specific requirement where in,

  • if a (boolean type) field in the request JSON body is absent altogether, then the request is valid.
  • If this field is set with a boolean value (true or false), then it is obviously valid.
  • If the field has non-boolean values, it should throw an exception.
  • If the field has empty value, it should throw an exception.

Even though the Java model throws an exception if the field is non-boolean by type checking, the empty value is being converted as null. Instead I need to be able to distinguish it and throw an exception. How can achieve this?

Here's how I defined the post body model and I am using the AutoValue generator so I don't have the setter function for the fields written by hand. Also, I am using the fasterxml library.

@JsonProperty("indicator")
@Nullable
public abstract Boolean getIndicator();

I have tried defining a custom annotation and writing the logic to check if the value is empty, but it didn't work.


Solution

  • You need to disable MapperFeature.ALLOW_COERCION_OF_SCALARS feature which allows coercion in cases like you have. See below example:

    import com.fasterxml.jackson.databind.MapperFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JsonApp {
    
        public static void main(String[] args) throws Exception {
            String json = "{\"indicator\":\"\"}";
    
            ObjectMapper mapper = new ObjectMapper();
            mapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
            System.out.println(mapper.readValue(json, BaseClass.class));
        }
    }
    
    class BaseClass {
        private Boolean indicator;
    
        public Boolean getIndicator() {
            return indicator;
        }
    
        public void setIndicator(Boolean indicator) {
            this.indicator = indicator;
        }
    
        @Override
        public String toString() {
            return "BaseClass{" +
                    "indicator=" + indicator +
                    '}';
        }
    }
    

    Above code prints:

    Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot coerce empty String ("") to Null value for type java.lang.Boolean (enable MapperFeature.ALLOW_COERCION_OF_SCALARS to allow) at [Source: (String)"{"indicator":""}"; line: 1, column: 14] (through reference chain: BaseClass["indicator"])