问题
i need to add alphanumeric field in play for that i am trying this code
object TestValidation {
implicit val readTestUser: Reads[TestValidation] = (
(JsPath \ "firstName").read(minLength[String](1)) and
(JsPath \ "lastName").read(minLength[String](1)) and
(JsPath \ "email").read(email) and
(JsPath \ "password").read(minLength[String](1)))(TestValidation.apply _)
i want the "password" field to be alphanumeric i have added this custom validation constraint now i want to intregate this during Reads method of json doing something like this maybe
(JsPath \ "password").read(minLength[String](1)).passwordCheckConstraint
i don't know the correct way to do this here is the constraint code
val allNumbers = """\d*""".r
val allLetters = """[A-Za-z]*""".r
val passwordCheckConstraint: Constraint[String] = Constraint("constraints.passwordcheck")({
plainText =>
val errors = plainText match {
case allNumbers() => Seq(ValidationError("Password is all numbers"))
case allLetters() => Seq(ValidationError("Password is all letters"))
case _ => Nil
}
if (errors.isEmpty) {
Valid
} else {
Invalid(errors)
}
})
please help
回答1:
Having constraints represented as types is generally a very good practice:
import play.api.data.validation._
import play.api.libs.json._
class Password private(val str: String)
object Password {
val passwordCheckConstraint: Constraint[String] = Constraint("constraints.passwordcheck")({
plainText =>
val allNumbers = """\d*""".r
val allLetters = """[A-Za-z]*""".r
val lengthErrors = Constraints.minLength(1).apply(plainText) match {
case Invalid(errors) => errors
case _ => Nil
}
val patternErrors: Seq[ValidationError] = plainText match {
case allNumbers() => Seq(ValidationError("Password is all numbers"))
case allLetters() => Seq(ValidationError("Password is all letters"))
case _ => Nil
}
val allErrors = lengthErrors ++ patternErrors
if (allErrors.isEmpty) {
Valid
} else {
Invalid(allErrors)
}
})
def validate(pass: String): Either[Seq[ValidationError],Password] = {
passwordCheckConstraint.apply(pass) match {
case Valid => Right(new Password(pass))
case Invalid(errors) => Left(errors)
}
}
implicit val format: Format[Password] = Format[Password](
Reads[Password](jsv => jsv.validate[String].map(validate).flatMap {
case Right(pass) => JsSuccess(pass)
case Left(errors) => JsError(Seq((JsPath \ 'password,errors)))
}),
Writes[Password](pass => Json.toJson(pass.str))
)
}
With these in place now you can write:
(JsPath \ 'password).read[Password] //return Password instance or errors
//or if you want to stick with the String type you can write this:
(JsPath \ 'password).read[Password].map(_.str)
Note that the play-json
's JsPath.read
method accepts only a single type argument and is not the same as html form validations.
来源:https://stackoverflow.com/questions/44202056/how-to-add-alphanumeric-field-in-play-framework