如何在对象上应用表单验证器
how to apply Form validators on object
我在 Scala 中有一个 API。当我想创建一个新用户时,我需要对某些字段(用户名、名字、姓氏)进行验证。我找不到将表单应用于我的案例 class 用户的解决方案。我以为使用 (User.apply
) 这会自动覆盖我的 User
class,但这并没有发生。
User.scala
case class User(
id: Int = 0,
userName: String,
firstName: String,
lastName: String
)
object User {
import play.api.libs.json._
implicit val jsonWrites = Json.writes[User]
implicit val userReads = Json.reads[User]
def tupled = (User.apply _).tupled
}
// Form validator for post requests
object UserForm {
val form: Form[User] = Form(
mapping(
"id" -> number,
"userName" -> text(minLength = 5),
"firstName" -> text(minLength = 5),
"lastName" -> nonEmptyText
)(User.apply)(User.unapply)
)
}
UsersController.scala
def create = Action(parse.json) { implicit request => {
val userFromJson = Json.fromJson[User](request.body)
userFromJson match {
case JsSuccess(user: User, path: JsPath) => {
var createdUser = Await.result(usersRepository.create(user), Duration.Inf)
Ok(Json.toJson(createdUser))
}
case error @ JsError(_) => {
println(error)
InternalServerError(Json.toJson("Can not create user"))
}
}
}
}
UsersRepository.scala
def create(user: User): Future[User] = {
val insertQuery = dbUsers returning dbUsers.map(_.id) into ((x, id) => x.copy(id = id))
val query = insertQuery += user
db.run(query)
}
(UsersRepository 在这个问题上没那么重要)
所以,当我阅读 json 时,我认为需要应用表单验证器
val userFromJson = Json.fromJson[User](request.body)
但什么也没发生。另一个问题是,如果我从客户端发送一个 null
参数,将出现错误,无法读取和创建用户。
例如:
"firstName": ""
- 空用户名将通过
"firstName": null
- 会失败
这取决于如何在客户端 (Angular) 中配置 User
class,构造函数中的字段为 null 或空。我更喜欢将它设置为 null,即使它是一个字符串,如果它不是必填字段(数据库中的 NULL 值比空单元格更好)
尝试使用这个:
request.body.validate[User]
还有一件事,你不应该使用
var createdUser = Await.result(usersRepository.create(user), Duration.Inf)
所以使用 val 而不是 var 和其他东西,你不需要强制 future 来解决,像这样使用它:
val createdUser = usersRepository.create(user)
createdUser.map(Ok(Json.toJson(_)))
并且您的操作应该是异步的。
求解决方案,我的Form需要是对象User的一部分,而不是另一个对象。
object User {
import play.api.libs.json._
implicit val jsonWrites = Json.writes[User]
implicit val userReads = Json.reads[User]
val form: Form[User] = Form(
mapping(
"id" -> number,
"userName" -> text(minLength = 2),
"firstName" -> text(minLength = 4),
"lastName" -> nonEmptyText
)(User.apply)(User.unapply)
)
def tupled = (User.apply _).tupled
}
控制器中的方法变为:
def create = Action(parse.json) { implicit request => {
User.form.bindFromRequest.fold(
formWithErrors => BadRequest(Json.toJson("Some form fields are not validated.")),
success => {
val userFromJson = Json.fromJson[User](request.body)
userFromJson match {
case JsSuccess(user: User, path: JsPath) => {
val createdUser = Await.result(usersRepository.create(user), Duration.Inf)
Ok(Json.toJson(createdUser))
}
case error@JsError(_) => {
println(error)
InternalServerError(Json.toJson("Can not create user"))
}
}
}
)
}
}
我知道,我需要格式化我的代码...在 Visual Studio 之后使用 IntelliJ 太烦人了:(
我在 Scala 中有一个 API。当我想创建一个新用户时,我需要对某些字段(用户名、名字、姓氏)进行验证。我找不到将表单应用于我的案例 class 用户的解决方案。我以为使用 (User.apply
) 这会自动覆盖我的 User
class,但这并没有发生。
User.scala
case class User(
id: Int = 0,
userName: String,
firstName: String,
lastName: String
)
object User {
import play.api.libs.json._
implicit val jsonWrites = Json.writes[User]
implicit val userReads = Json.reads[User]
def tupled = (User.apply _).tupled
}
// Form validator for post requests
object UserForm {
val form: Form[User] = Form(
mapping(
"id" -> number,
"userName" -> text(minLength = 5),
"firstName" -> text(minLength = 5),
"lastName" -> nonEmptyText
)(User.apply)(User.unapply)
)
}
UsersController.scala
def create = Action(parse.json) { implicit request => {
val userFromJson = Json.fromJson[User](request.body)
userFromJson match {
case JsSuccess(user: User, path: JsPath) => {
var createdUser = Await.result(usersRepository.create(user), Duration.Inf)
Ok(Json.toJson(createdUser))
}
case error @ JsError(_) => {
println(error)
InternalServerError(Json.toJson("Can not create user"))
}
}
}
}
UsersRepository.scala
def create(user: User): Future[User] = {
val insertQuery = dbUsers returning dbUsers.map(_.id) into ((x, id) => x.copy(id = id))
val query = insertQuery += user
db.run(query)
}
(UsersRepository 在这个问题上没那么重要)
所以,当我阅读 json 时,我认为需要应用表单验证器
val userFromJson = Json.fromJson[User](request.body)
但什么也没发生。另一个问题是,如果我从客户端发送一个 null
参数,将出现错误,无法读取和创建用户。
例如:
"firstName": ""
- 空用户名将通过
"firstName": null
- 会失败
这取决于如何在客户端 (Angular) 中配置 User
class,构造函数中的字段为 null 或空。我更喜欢将它设置为 null,即使它是一个字符串,如果它不是必填字段(数据库中的 NULL 值比空单元格更好)
尝试使用这个:
request.body.validate[User]
还有一件事,你不应该使用
var createdUser = Await.result(usersRepository.create(user), Duration.Inf)
所以使用 val 而不是 var 和其他东西,你不需要强制 future 来解决,像这样使用它:
val createdUser = usersRepository.create(user)
createdUser.map(Ok(Json.toJson(_)))
并且您的操作应该是异步的。
求解决方案,我的Form需要是对象User的一部分,而不是另一个对象。
object User {
import play.api.libs.json._
implicit val jsonWrites = Json.writes[User]
implicit val userReads = Json.reads[User]
val form: Form[User] = Form(
mapping(
"id" -> number,
"userName" -> text(minLength = 2),
"firstName" -> text(minLength = 4),
"lastName" -> nonEmptyText
)(User.apply)(User.unapply)
)
def tupled = (User.apply _).tupled
}
控制器中的方法变为:
def create = Action(parse.json) { implicit request => {
User.form.bindFromRequest.fold(
formWithErrors => BadRequest(Json.toJson("Some form fields are not validated.")),
success => {
val userFromJson = Json.fromJson[User](request.body)
userFromJson match {
case JsSuccess(user: User, path: JsPath) => {
val createdUser = Await.result(usersRepository.create(user), Duration.Inf)
Ok(Json.toJson(createdUser))
}
case error@JsError(_) => {
println(error)
InternalServerError(Json.toJson("Can not create user"))
}
}
}
)
}
}
我知道,我需要格式化我的代码...在 Visual Studio 之后使用 IntelliJ 太烦人了:(