SpringBoot atomically convert integer to boolean with @RequestBody annotation? How can I reject integer to be converted to boolean?

ぐ巨炮叔叔 提交于 2020-07-30 15:30:09

问题


My request was an application/json type like this: {"able": true}, but when I send the request like this {"able":12345}, the field able still can get a correct value true. Why?

@PatchMapping("/{id}/path/{name}")
public ResponseEntity someMethod(
    @Valid @RequestBody SomeRequest request) {
    // do something
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class SomeRequest {
    @AssertTrue
    @NotNull
    private Boolean able;
}

回答1:


Because jackson.databind will parse int to bool when field type is bool. Find code in NumberDeserializers.BooleanDeserializer

            JsonToken t = p.getCurrentToken();
            if (t == JsonToken.VALUE_TRUE) {
                return Boolean.TRUE;
            }
            if (t == JsonToken.VALUE_FALSE) {
                return Boolean.FALSE;
            }
            return _parseBoolean(p, ctxt);

_parseBoolean(p, ctxt) will parse int to bool.

We can do it by ourselves not use default.

  1. Create our bool deser class.
public class MyDeser extends JsonDeserializer {
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken t = p.getCurrentToken();
        if (t == JsonToken.VALUE_TRUE) {
            return Boolean.TRUE;
        }
        if (t == JsonToken.VALUE_FALSE) {
            return Boolean.FALSE;
        }
        return null; 
        // not parse int to bool but null and it may work ok.
        // if throw new IOException(), it will work fail. Maybe return null means use other deser to deal it. throw Exception means fail. I don't know it clearly.
    }
}
  1. Create a configuration and inject a SimpleModule bean. I write in application
 @SpringBootApplication
 @Configuration
 public class DemoApplication {
     @Bean
     public SimpleModule addDeser() {
         return new SimpleModule().addDeserializer(Boolean.class, new MyDeser());
     }
     public static void main(String[] args) {
         SpringApplication.run(DemoApplication.class, args);
     }
 }



回答2:


Maybe because each non-zero integer value is true? What happens if you sent {"able":0} ?




回答3:


Each non zero value will be treated as true in boolean case. If you send zero then it will set value to false.




回答4:


Actually the answer posted by sunsunsun is exactly. It works well. But my answer is re-code the setter method of SomeRequest like this:

    public void setAble(Object value) {
        if (value instanceof Boolean) {
            submitted = (Boolean) value;
        }
        if ("true".equals(value)) {
            submitted = true;
        }
    }

Because Jackson is using the setter method to inject value.

And then I can just accept the value which is true or "true". And I don't want to affect others.



来源:https://stackoverflow.com/questions/59353379/springboot-atomically-convert-integer-to-boolean-with-requestbody-annotation-h

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!