首页 > 解决方案 > SpringBoot 使用@RequestBody 注释原子地将整数转换为布尔值?如何拒绝将整数转换为布尔值?

问题描述

我的请求是这样的application/json类型:{"able": true},但是当我这样发送请求时{"able":12345},该字段able仍然可以获得正确的值true。为什么?

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

标签: javaspring-bootvalidationspring-mvc

解决方案


因为当字段类型为 bool 时,jackson.databind 会将 int 解析为 bool。在中查找代码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)将 int 解析为 bool。

我们可以自己做,不使用默认值。

  1. 创建我们的 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. 创建一个配置并注入一个 SimpleModule bean。我在申请中写
 @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);
     }
 }

推荐阅读