Play Framework 2.3(Scala)中的自定义JSON验证约束
发布时间:2020-12-16 18:58:23 所属栏目:安全 来源:网络整理
导读:我设法使用自定义约束来实现表单验证,但是现在我想对 JSON数据做同样的事情. 如何将自定义验证规则应用于JSON解析器? 示例:客户端的POST请求包含一个用户名(username),不仅要确保该参数是非空文本,而且该用户实际上存在于数据库中. // In the controller..
我设法使用自定义约束来实现表单验证,但是现在我想对
JSON数据做同样的事情.
如何将自定义验证规则应用于JSON解析器? 示例:客户端的POST请求包含一个用户名(username),不仅要确保该参数是非空文本,而且该用户实际上存在于数据库中. // In the controller... def postNew = Action { implicit request => request.body.asJson.map { json => json.validate[ExampleCaseClass] match { case success: JsSuccess[ExampleCaseClass] => val obj: ExampleCaseClass = success.get // ...do something with obj... Ok("ok") case error: JsError => BadRequest(JsError.toFlatJson(error)) } } getOrElse(BadRequest(Json.obj("msg" -> "JSON request expected"))) } // In ExampleCaseClass.scala... case class ExampleCaseClass(username: String,somethingElse: String) object ExampleCaseClass { // That's what I would use for a form: val userCheck: Mapping[String] = nonEmptyText.verifying(userExistsConstraint) implicit val exampleReads: Reads[ExampleCaseClass] = ( (JsPath "username").read[String] and (JsPath "somethingElse").read[String] )(ExampleCaseClass.apply _) } 这是我得到的,但这只能确保用户名是一个字符串.如何应用我的附加自定义验证规则,例如检查给定用户是否真的存在?这甚至可能吗 当然,我可以把我的obj放在案例的成功部分,并在那里执行额外的检查,但这似乎不是很优雅,因为那时我必须创建自己的错误信息,只能使用用户JsError.toFlatJson(错误).搜索和尝试几个小时后,我找不到任何例子. 对于常规表单,我会使用这样的东西: // In the controller object... val userValidConstraint: Constraint[String] = Constraint("constraints.uservalid")({ username => if (User.find(username).isDefined) { Valid } else { val errors = Seq(ValidationError("User does not exist")) Invalid(errors) } }) val userCheck: Mapping[String] = nonEmptyText.verifying(userValidConstraint) val exampleForm = Form( mapping( "username" -> userCheck // ...and maybe some more fields... )(ExampleCaseClass.apply)(ExampleCaseClass.unapply) ) // In the controller's action method... exampleForm.bindFromRequest.fold( formWithErrors => { BadRequest("Example error message") },formData => { // do something Ok("Valid!") } ) 但是如果以JSON格式提交数据呢? 解决方法
我可以想到的最简单的方法将使用Reads的过滤器方法.
假设我们有一些User对象将确定用户名是否存在: object User { def findByName(name: String): Option[User] = ... } 然后,您可以构建您的Reads,如下所示: import play.api.libs.json._ import play.api.libs.functional.syntax._ import play.api.data.validation._ case class ExampleCaseClass(username: String,somethingElse: String) object ExampleCaseClass { implicit val exampleReads: Reads[ExampleCaseClass] = ( (JsPath "username").read[String].filter(ValidationError("User does not exist."))(findByName(_).isDefined) and (JsPath "somethingElse").read[String] )(ExampleCaseClass.apply _) } 您的控制器功能可以使用json BodyParser进行简化和折叠: def postNew = Action(parse.json) { implicit request => request.body.validate[ExampleCaseClass].fold( error => BadRequest(JsError.toFlatJson(error)),obj => { // Do something with the validated object.. } ) } 您还可以创建一个单独的Reads [String],它将检查用户是否存在,并在Reads [ExampleCaseClass]中明确使用Reads [String]: val userValidate = Reads.StringReads.filter(ValidationError("User does not exist."))(findByName(_).isDefined) implicit val exampleReads: Reads[ExampleCaseClass] = ( (JsPath "username").read[String](userValidate) and (JsPath "somethingElse").read[String] )(ExampleCaseClass.apply _) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |