Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Json Single Field Reads Validator

I'm trying to add simple validation to incoming Json in Play. Based on this question, I tried writing:

case class ApiData(data: String)

def maxLengthValidator = Reads.StringReads.filter(ValidationError("Error"))(_.length < 100)

implicit val ApiDataReads: Reads[ApiData] = (
  (JsPath \ "data").read[String](maxLengthValidator)
)(ApiData.apply _)

This does not compile, producing the error:

type mismatch;
[error]  found   : String => ApiData
[error]  required: play.api.libs.json.Reads[?]
[error]     )(ApiData.apply _)
[error]                        ^
[error] one error found

But if I add a second field, it does compile:

case class ApiData(data: String, __doNotUse: Option[Int])

implicit val ApiDataReads: Reads[ApiData] = (
  (JsPath \ "data").read[String](maxLengthValidator) and
  (JsPath \ "__doNotUse").readNullable[Int]
)(ApiData.apply _)

What do I need to do to get this working with just a single field?

like image 272
Matt Bierner Avatar asked Mar 17 '23 11:03

Matt Bierner


1 Answers

Since you only have a single field, you don't need the combinator syntax to create a reads, you can just use the functions already defined on Reads to build the one you want.

def maxLengthValidator = Reads.of[String].filter(ValidationError("Error"))(_.length < 100)

case class ApiData(data: String)

object ApiData {

  implicit val reads: Reads[ApiData] = (__ \ "data").read(maxLengthValidator).map(ApiData.apply _)

}

You start with a Reads[String], add some validation (filter) and then transform valid results to your own rich type (map).

like image 129
Ryan Avatar answered Mar 20 '23 00:03

Ryan