简体   繁体   English

SpringBoot 使用@RequestBody 注释原子地将整数转换为布尔值? 如何拒绝将整数转换为布尔值?

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

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 .我的请求是这样的application/json类型: {"able": true} ,但是当我发送这样的请求时{"able":12345} ,字段able仍然可以获得正确的值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;
}

Because jackson.databind will parse int to bool when field type is bool.因为当字段类型为 bool 时,jackson.databind 会将 int 解析为 bool。 Find code in NumberDeserializers.BooleanDeserializerNumberDeserializers.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. _parseBoolean(p, ctxt)将 int 解析为 bool。

We can do it by ourselves not use default.我们可以自己做,不使用默认值。

  1. Create our bool deser class.创建我们的 bool deser 类。
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.创建一个配置并注入一个 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);
     }
 }

Actually the answer posted by sunsunsun is exactly.实际上, sunsunsun发布的答案正是如此。 It works well.它运作良好。 But my answer is re-code the setter method of SomeRequest like this:但我的答案是重新编码SomeRequest的 setter 方法,如下所示:

    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.因为 Jackson 是使用 setter 方法注入值。

And then I can just accept the value which is true or "true".然后我可以接受为真或“真”的值。 And I don't want to affect others.而且我不想影响别人。

create a Custom BooleanDeserializer by extending the JsonDeserializer from jackson library,通过从杰克逊库扩展 JsonDeserializer 创建自定义 BooleanDeserializer,

public class BooleanValueDeserializer extends JsonDeserializer<Boolean> {

@Override
public Boolean deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JacksonException {
    try {
        return jsonParser.getBooleanValue();
    }catch(JsonParseException exception) {
        throw new RuntimeException(String.format("%s is not a valid Boolean value for %s", jsonParser.getText(), jsonParser.getCurrentName()));
    }
}
}

and add the following annotation on the Request Object for Deserialization并在请求对象上添加以下注释以进行反序列化

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SomeRequest {
    @NotNull
    @JsonDeserialize(using = BooleanValueDeserializer.class)
    private Boolean able;
}

Maybe because each non-zero integer value is true?也许是因为每个非零整数值都是真的? What happens if you sent {"able":0} ?如果您发送{"able":0}会发生什么?

Each non zero value will be treated as true in boolean case.在布尔情况下,每个非零值都将被视为真。 If you send zero then it will set value to false.如果你发送零,那么它会将值设置为 false。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM