Ktor:如何验证 JSON 请求?

Ali*_*uis 7 json kotlin ktor

我已经知道如何接收 JSON 对象并自动将其反序列化为所需的格式(例如,使用数据类)。另请参阅如何在 Ktor 中接收 JSON 对象?

我现在的问题是我想验证 JSON 请求,BadRequest如果它不是所需的格式,则返回,类似于 Django:https : //stackoverflow.com/a/44085405/5005715

我怎样才能在 Ktor/Kotlin 中做到这一点?不幸的是,我在文档中找不到解决方案。此外,必填/可选字段会很好。

And*_*ann 6

这是一个快速示例,说明如何在需要时使用 400 进行验证和响应。

fun main(args: Array<String>) {
    embeddedServer(Netty, 5000) {
        install(CallLogging)
        install(ContentNegotiation) { gson { } }
        install(Routing) {
            post("test") {
                val sample = call.receive<Sample>()
                if (!sample.validate()) {
                    call.respond(HttpStatusCode.BadRequest, "Sample did not pass validation")
                }
                call.respond("Ok")
            }
        }
    }.start()
}

fun Sample.validate(): Boolean = id > 5

data class Sample(val id: Int)

Run Code Online (Sandbox Code Playgroud)

你有什么别的想法吗?

没有内置的注释等。


Sah*_*bra 6

您可以hibernate-validator用于输入验证。参考以下:

添加依赖(Gradle):

compile "org.hibernate.validator:hibernate-validator:6.1.1.Final"
Run Code Online (Sandbox Code Playgroud)

注释您的数据类 (DTO):

data class SampleDto(
    @field:Min(value=100)
    val id: Int,
    @field:Max(value=99)
    val age: Int
)
Run Code Online (Sandbox Code Playgroud)

在路由中添加验证器:

import javax.validation.Validation

fun Application.module() {

    val service = SampleService()
    val validator = Validation.buildDefaultValidatorFactory().validator

    routing {
        post("/sample/resource/") {
            val sampleDto = call.receive<SampleDto>()
            sampleDto.validate(validator)
            service.process(sampleDto)
            call.respond(HttpStatusCode.OK)
        }
    }
}

@Throws(BadRequestException::class)
fun <T : Any> T.validate(validator: Validator) {
    validator.validate(this)
        .takeIf { it.isNotEmpty() }
        ?.let { throw BadRequestException(it.first().messageWithFieldName()) }
}

fun <T : Any> ConstraintViolation<T>.messageWithFieldName() = "${this.propertyPath} ${this.message}"
Run Code Online (Sandbox Code Playgroud)

奖励步骤(可选) - 添加异常处理程序:

fun Application.exceptionHandler() {

    install(StatusPages) {
        exception<BadRequestException> { e ->
            call.respond(HttpStatusCode.BadRequest, ErrorDto(e.message, HttpStatusCode.BadRequest.value))
            throw e
        }
    }

}

data class ErrorDto(val message: String, val errorCode: Int)
Run Code Online (Sandbox Code Playgroud)