Restrições de validação JSON personalizadas no Play Framework 2.3 (Scala)
Consegui implementar a validação de formulário com restrições personalizadas, mas agora quero fazer o mesmo com os dados JSON.
Como posso aplicar regras de validação personalizadas a um analisador JSON?
Exemplo: a solicitação POST do cliente contém um nome de usuário (username
) e não apenas quero garantir que esse parâmetro seja um texto não vazio, mas também que esse usuário realmente exista no banco de dados.
// 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 _)
}
Isso é o mais longe que eu chego, mas isso só garante queusername
é uma string.Como aplico minha regra de validação personalizada adicional, por exemplo. verificar se o usuário fornecido realmente existe? Isso é possível?
Claro, eu poderia pegar minhaobj
nocase success
na ação e execute verificações adicionais lá, mas isso não parece muito elegante, porque então eu teria que criar minha própria mensagem de erro e só poderia usar o usuárioJsError.toFlatJson(error)
para alguns casos. Depois de pesquisar e tentar por horas, não consegui encontrar nenhum exemplo.
Para formulários regulares, eu usaria algo como isto:
// 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!")
}
)
Mas e se os dados forem enviados como JSON?