如何在对象上应用表单验证器

时间:2019-09-26 11:49:17

标签: forms scala validation playframework play-json

我在Scala中有一个API。当我想创建一个新用户时,我需要在某些字段(用户名,名字,姓氏)上使用验证器。我找不到在案例类User上应用Form的解决方案。我以为使用(User.apply)会自动覆盖我的User类,但这没有发生。

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类,在构造函数中字段为null还是为空。我宁愿将其设置为null,即使是字符串,也不是必填字段(数据库中的NULL值比空单元格更好)

2 个答案:

答案 0 :(得分:0)

尝试使用此功能:

request.body.validate[User]

另一件事,您不应使用

var createdUser = Await.result(usersRepository.create(user), Duration.Inf)

因此,使用val´s而不是var´s,您无需强迫未来解决,就可以像这样使用它:

val createdUser = usersRepository.create(user)
createdUser.map(Ok(Json.toJson(_)))

您的操作应该是异步的。

答案 1 :(得分:0)

找到一个解决方案,我的表单需要成为对象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
}

,Controller中的方法变为:

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太烦人了:(