我已经知道如何接收 JSON 对象并自动将其反序列化为所需的格式(例如,使用数据类)。另请看这里:如何在 Ktor 中接收 JSON 对象?
我现在的问题是我想验证 JSON 请求并BadRequest
在它不是所需格式时返回,类似于 Django:https ://stackoverflow.com/a/44085405/5005715
我如何在 Ktor/Kotlin 中做到这一点?不幸的是,我在文档中找不到解决方案。此外,必填/可选字段会很好。
我已经知道如何接收 JSON 对象并自动将其反序列化为所需的格式(例如,使用数据类)。另请看这里:如何在 Ktor 中接收 JSON 对象?
我现在的问题是我想验证 JSON 请求并BadRequest
在它不是所需格式时返回,类似于 Django:https ://stackoverflow.com/a/44085405/5005715
我如何在 Ktor/Kotlin 中做到这一点?不幸的是,我在文档中找不到解决方案。此外,必填/可选字段会很好。
您可以hibernate-validator
用于输入验证。参考以下:
添加依赖项(Gradle):
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)
这是一个快速示例,说明如何在需要时使用 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)
你有别的想法吗?
没有内置注释等。
进一步了解 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
)
使用这个库
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()
}
}
}
我不确定 Ktor 是否已经为此提供了一些东西。Spring 使用@Valid 注释很好地处理了它。我也在寻找这样的东西来验证json还是对象。我找到了这个框架https://github.com/making/yavi。看起来很有趣。我会试一试