Fasterxml Jackson automatically converts non-boolean value to a boolean value

fasterxml, jackson, java, json, serialization

Solution

There are two ways of doing this assuming that you will map boolean field as Object type as HARDI answered -

1. Customize the setter method -

    public class DTO {
    String key1;
    Object booleanKey;

    public Object getBooleanKey() {
        return booleanKey;
    }

    public void setBooleanKey(Object booleanKey) {
        if (booleanKey instanceof Boolean) {
            this.booleanKey = booleanKey;
        } else {
            // custom code here
        }

    }

    public String getKey1() {
        return key1;
    }

    public void setKey1(String key1) {
        this.key1 = key1;
    }
    }

2. Write Custom Deserializer -

class BooleanKeyDeserializer extends JsonDeserializer<Object> {

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    Object object = p.readValueAs(Object.class);
    if (!(object instanceof Boolean)) {
        // custom code here
    }
    return object;
}
}

Annotate the field for which you want to perform custom deserialization -

class DTO {
String key1;
@JsonDeserialize(using = BooleanKeyDeserializer.class)
Object booleanKey;
//setters getters
}

Problem

I have a pojo class where one of the flag `isControl` which is of type Boolean. When this property gets a non boolean value other than `true or false` fasterxml jackson automatically converts the input value to `true`. After debugging for few hours I find out that this is happening in the setter method `setIsControl`. I want to pass a custom message if input value for this property is non-boolean. I have written my own annotation to validate the input value for this property and return custom message if its not a boolean value but jackson binds the value before checking my custom validator. Using jackson version >>> `2.6.3`. Any help will be appreciated. Control.java ``` @JsonProperty(required = true) @NotNull(message = "isControl cannot be null") private Boolean isControl; public Boolean getIsControl() { return isControl; } @CheckBoolean(fieldName = "isControl") public void setIsControl(Boolean isControl) { this.isControl = isControl; } public class BooleanValidator implements ConstraintValidator<CheckBoolean, Boolean> { private String fieldName; @Override public void initialize(CheckBoolean constraintAnnotation) { this.fieldName = constraintAnnotation.fieldName(); } @Override public boolean isValid(Boolean value, ConstraintValidatorContext context) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate( String.format("The control flag %s should be either true or false", fieldName)) .addConstraintViolation(); if (value != null) { boolean isBoolean; if (value instanceof Boolean) { isBoolean = ((Boolean)value).booleanValue(); System.out.println("var isBoolean: " +isBoolean); return true; } else if (value instanceof Boolean && Boolean.FALSE.equals(value)) { isBoolean = ((Boolean)value).booleanValue(); return true; } else { return false; } } return false; } } ``` Exception:

Original source