Ktor:如何验证JSON请求?

时间:2019-01-15 17:39:52

标签: json kotlin ktor

我已经知道如何接收JSON对象并自动将其反序列化为所需格式(例如,使用数据类)。也请看这里:How to receive JSON object in Ktor?

我现在的问题是,我想验证JSON请求并返回BadRequest(如果不是所需的格式),例如Django:https://stackoverflow.com/a/44085405/5005715

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

5 个答案:

答案 0 :(得分:2)

您可以使用hibernate-validator进行输入验证。请参阅以下内容:

添加依赖项(等级):

compile "org.hibernate.validator:hibernate-validator:6.1.1.Final"

注释您的数据类(DTO):

data class SampleDto(
    @field:Min(value=100)
    val id: Int,
    @field:Max(value=99)
    val age: Int
)

在路由中添加验证器:

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}"

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

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)

答案 1 :(得分:1)

这是一个简单的示例,说明如何根据需要验证和响应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)

您还有其他想法吗?

没有内置注释或类似内容。

答案 2 :(得分:0)

不确定Ktor是否已经为此准备好了。Spring使用 @有效注释可以很好地处理它。 我也在寻找这样的东西来验证json或对象。我找到了这个框架https://github.com/making/yavi。看起来很有趣。我会尝试

答案 3 :(得分:0)

更进一步地回答Andreas,您可以在请求无效时返回错误列表,如下所示:

    post {
        val postDog = call.receive<PostDog>()
        val validationErrors = postDog.validate()
        if (validationErrors.isEmpty()) {

            // Save to database

        } else {
            call.respond(HttpStatusCode.BadRequest, validationErrors)
        }

    }

    fun PostDog.validate() : List<Error> {
        var validationErrors : MutableList<Error> = mutableListOf()
        if(name == null || name.isBlank())
            validationErrors.add(Error(code = "dog.name.required", message = "Dog requires a name"))
        if(color == null || color.isBlank())
            validationErrors.add(Error(code = "dog.color.required", message = "Dog requires a color"))            
        return validationErrors
    }

    data class PostDog(
      val name: String,
      val color: String          
    )

    data class Error(
        val code : String,
        val message : String
    )

答案 4 :(得分:0)

使用这个库

https://github.com/valiktor/valiktor

data class Employee(val id: Int, val name: String, val email: String) {
        init {
            validate(this) {
                validate(Employee::id).isPositive()
                validate(Employee::name).hasSize(min = 3, max = 80)
                validate(Employee::email).isNotBlank().isEmail()
            }
        }
    }