Spring not null验证在kotlin中引发HttpMessageTreadableException而不是MethodArgumentNotValidException

Spring not null验证在kotlin中引发HttpMessageTreadableException而不是MethodArgumentNotValidException,spring,rest,validation,kotlin,Spring,Rest,Validation,Kotlin,我正在使用Spring在Kotlin中创建一个简单的应用程序,但我在验证方面遇到了问题 我有这个实体类: @Entity @Table(name = "category") data class Category( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long?, @field:NotNull @field:NotEmpty val name

我正在使用Spring在Kotlin中创建一个简单的应用程序,但我在验证方面遇到了问题

我有这个实体类:

@Entity
@Table(name = "category")
data class Category(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Long?,
        @field:NotNull @field:NotEmpty val name: String)
我的控制器的功能如下:

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@Valid @RequestBody category: Category): ResponseEntity<Category>
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
乐趣创建(@Valid@RequestBody category:category):ResponseEntity

create
有一些代码,但这与问题无关,我的问题是请求主体验证。如果我发送一个名称字段为空的类别,它将抛出一个
MethodArgumentNotValidException
异常,但是如果我将null发送到
name
字段,则会抛出一个异常
HttpMessageEndableException
。有人知道是否可以将null传递给标记为
@NotNull
的字段,以便在Kotlin中也抛出
MethodArgumentNotValidException

因此,您的问题是将name字段指定为不可为null,默认情况下,kotlin的jackson模块将对其进行检查,并在json映射过程中抛出
HttpMessageEndableException
,这是由
MissingKotlinParameterException
引起的。如果您将
name
字段标记为可空json映射,并使用
@Valid
进入spring验证阶段,那么我们将获得
MethodArgumentNotValidException

@Entity
@Table(name = "category")
data class Category(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long?,
    @field:NotNull @field:NotEmpty val name: String?)

您可以通过提供
httpmessagenoteradableexception
处理程序来处理此问题 然后检查根本原因是否为
MissingKotlinParameterException

之后,您可以提供自定义验证错误。我使用的是
zalando问题
,因此语法与vanilla spring有点不同,但您可以理解:

    @ExceptionHandler
    override fun handleMessageNotReadableException(
        exception: HttpMessageNotReadableException,
        request: NativeWebRequest
    ): ResponseEntity<Problem> {
        // workaround
        val cause = exception.cause
        if (cause is MissingKotlinParameterException) {
            val violations = setOf(createMissingKotlinParameterViolation(cause))
            return newConstraintViolationProblem(exception, violations, request)
        }
        return create(Status.BAD_REQUEST, UnableToReadInputMessageProblem(), request)
    }

    private fun createMissingKotlinParameterViolation(cause: MissingKotlinParameterException): Violation {
        val name = cause.path.fold("") { jsonPath, ref ->
            val suffix = when {
                ref.index > -1 -> "[${ref.index}]"
                else -> ".${ref.fieldName}"
            }
            (jsonPath + suffix).removePrefix(".")
        }
        return Violation(name, "must not be null")
    }
@ExceptionHandler
重写fun HandleMessageGenetradableException(
异常:HttpMessageDataableException,
请求:NativeWebRequest
):响应性{
//变通办法
val cause=exception.cause
如果(原因是缺少KotlinParameterException){
val违规=setOf(createMissingKotlinParameterViolation(原因))
返回newConstraintViolationProblem(异常、冲突、请求)
}
返回创建(Status.BAD_请求,UnableToReadInputMessageProblem(),请求)
}
private fun createMissingKotlinParameterViolation(原因:MissingKotlinParameterException):违反{
val name=cause.path.fold(“”{jsonPath,ref->
val后缀=何时{
ref.index>-1->“[${ref.index}]”
else->“${ref.fieldName}”
}
(jsonPath+后缀).removePrefix(“.”)
}
返回冲突(名称“不得为空”)
}
通过这种方式,您可以获得具有适当约束错误的良好输出

您可以尝试直接为
MissingKotlinParameterException
声明
@ExceptionHandler
(虽然我已经尝试过,但不是出于某种原因),但我不能保证它会工作

路径解析的代码示例取自