Fasterxml Jackson自动将非布尔值转换为布尔值

4

我有一个POJO类,其中一个标志isControl是布尔类型。

当该属性获得一个非布尔值而不是true或false时,fasterxml jackson会自动将输入值转换为true。经过几个小时的调试,我发现这是发生在setter方法setIsControl中。

如果此属性的输入值不是布尔值,我想传递自定义消息。我编写了自己的注释来验证此属性的输入值,并在其不是布尔值时返回自定义消息,但jackson会在检查我的自定义验证器之前绑定该值。

使用的Jackson版本 >>> 2.6.3。任何帮助将不胜感激。

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;
}
}

异常:

2个回答

2
假设您将布尔字段映射为对象类型,有两种方法可以实现这一点,如HARDI所回答的: 1. 自定义setter方法 -
    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. 编写自定义反序列化器 -

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;
}
}

为需要进行自定义反序列化的字段添加注释 -

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

1
只是好奇想知道,这是Jackson Api的一个错误吗?在任何最新版本的jackson api中是否已经处理了它,以便我们可以避免编写自定义反序列化程序?请给予建议。 - Prasanna
似乎 Jackson 2.9 已经实现了这个功能:ALLOW_COERCION_OF_SCALARS - second

1
我认为这是因为setter将其设置为布尔值。以下代码可以正常工作。在这种情况下,我在反序列化类中将布尔值作为对象进行了处理。
public class Json {
    private String key1;
    private Object booleanKey;
    public String getKey1() {
        return key1;
    }
    public void setKey1(String key1) {
        this.key1 = key1;
    }
    public Object getBooleanKey() {
        return booleanKey;
    }
    public void setBooleanKey(Object booleanKey) {
        this.booleanKey = booleanKey;
    }
}

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        String jsonString = "{\"key1\" : \"value1\", \"booleanKey\" : true}";

        ObjectMapper mapper = new ObjectMapper();
        Json obj = mapper.readValue(jsonString,Json.class);
        if (obj.getBooleanKey() instanceof Boolean) {
            System.out.println("booleanKey is boolean");
        } else {
            System.out.println("booleanKey is some other beast");
        }


        jsonString = "{\"key1\" : \"value1\", \"booleanKey\" : \"test\"}";
        obj = mapper.readValue(jsonString, Json.class);
        if (obj.getBooleanKey() instanceof Boolean) {
            System.out.println("booleanKey is boolean");
        } else {
            System.out.println("booleanKey is some other beast");
        }
    }

谢谢Hardi指引我方向,由于我需要在许多地方进行更改,我能否有一些自定义注释,如果它不是布尔值,我可以发送自定义消息?请建议。 - Prasanna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接