4

I am using play Reads validation helpers i want to show some custom message in case of json exception eg:length is minimum then specified or the given email is not valid , i knnow play displays the error message like this error.minLength but i want to display a reasonable message like please enter the character greater then 1 (or something ) here is my code

case class DirectUserSignUpValidation(firstName: String,
                                      lastName: String,
                                      email: String,
                                      password: String) extends Serializable

object DirectUserSignUpValidation {
  var validationErrorMsg=""
  implicit val readDirectUser: Reads[DirectUserSignUpValidation] = (
  (JsPath \ "firstName").read(minLength[String](1)) and
    (JsPath \ "lastName").read(minLength[String](1)) and
    (JsPath \ "email").read(email) and
    (JsPath \ "password").read(minLength[String](8).
      filterNot(ValidationError("Password is all numbers"))(_.forall(_.isDigit)).
      filterNot(ValidationError("Password is all letters"))(_.forall(_.isLetter))
    )) (UserSignUpValidation.apply _)
}

i have tried to add ValidationErrorlike this

 (JsPath \ "email").read(email,Seq(ValidationError("email address not correct")) and
   but its giving me compile time error


  too many arguments for method read: (t: T)play.api.libs.json.Reads[T]

please helo how can i add custom validationError messages while reading json data

swaheed
  • 3,671
  • 10
  • 42
  • 103
  • ```JsPath.read``` doesn't work like html form validation arguments. you asked this same question on [link](https://stackoverflow.com/questions/44202056/how-to-add-alphanumeric-field-in-play-framework/44221781#44221781) It would be nice if you read the answer to questions that you ask... – shayan May 30 '17 at 13:08

2 Answers2

6

There is no such thing as (JsPath \ "firstName").read(minLength[String](1)) in play json. what you can do with custom error message is this:

(JsPath \ "firstName")
  .read[String]
  .filter(ValidationError("your.error.message"))(_.length > 0)
shayan
  • 1,211
  • 9
  • 12
  • Actually, you can do `(JsPath \ "firstName").read(minLength[String](1))` (although I also find it strange that the `String` type parameter is not given to `read`). It just does not give the custom error message. – Cyrille Corpet Jun 01 '17 at 09:01
  • @CyrilleCorpet ```(JsPath \ "firstName").read[T](t: T)``` just returns whatever argument given as is without any validation. it's purpose is not validation but assignment of constant value. such as ```(JsPath \ "firstName").read("John")``` – shayan Jun 02 '17 at 05:06
  • 1
    this is not the method I'm talking about. Rather `(JsPath \ "firstName").read[T](t: Reads[T]): Reads[T]`. `minLength[String](1)` (for which I gave signature and implementation in my answer) is a `Reads[String]` with minimal size. – Cyrille Corpet Jun 02 '17 at 05:31
  • @CyrilleCorpet Yes I understand. what I'm saying is that if he writes ```(JsPath \ "firstName").read(minLength[String](1))``` playjson will resolve the firstName field as a ```Constraint[String]``` which is just wrong. hence my reply "There is no such thing as ```(JsPath \ "firstName").read(minLength[String](1))``` in play json" – shayan Jun 02 '17 at 06:12
  • Whoah, I was really slow, but I finally got what you meant! However, I tried this, and IntelliJ inferred the type as `Reads[String]`, not `Reads[Reads[String]]`, so there must be something in ambiguous method calls resolution that makes it prefer the second one in this case. – Cyrille Corpet Jun 02 '17 at 07:32
2

ValidationError messages are supposed to be keys to be used for translation, not human readable messages.

However, if you still want to change the message for minLength, you'll need to reimplement it, since it is hard-coded.

Thankfully, the source code is available, so you can easily change it as you please:

def minLength[M](m: Int)(implicit reads: Reads[M], p: M => scala.collection.TraversableLike[_, M]) =
  filterNot[M](JsonValidationError("error.minLength", m))(_.size < m)

If you want to use a more generic pattern to specify errors, the only access you have is using the result from your validation. For instance, you could do

val json: JsValue = ???
json.validate[DirectUserSignUpValidation] match {
  case JsSuccess(dusuv, _) => doSomethingWith(dusuv)
  case JsError(errs) => doSomethingWithErrors(errs)
}

Or, with a more compact approach

json.validate[DirectUserSignUpValidation].
  fold(doSomethingWithErrors, doSomethingWith)
Cyrille Corpet
  • 5,265
  • 1
  • 14
  • 31