Search code examples
scalaplayframeworkplay-json

Transform Value In PlayJSon Mapping


I'm performing a standard mapping of JSON to a case class using PlayJson. I'd like to transform the value that gets mapped to a member, Test.foo below, if the validation succeeds. Is it possible to work that into the definition of a Reads converter?

val json = .....

case class Test(foo:String, bar:String)

val readsTest: Reads[Test] = (
  (__ \ "foo").read[String](minLength(5)) and // And I want to transform this value if the validation succeeds
  (__ \ "bar").read[String](minLength(10))
)(Test.apply _)


json.validate[Test] match {
  case s: JsSuccess[Test] => s.get
  case e: JsError => false
}

Solution

  • Reads.map can do just that, for example, say we want to reverse the value of foo field, then we could call .map(v => v.reverse) on the Reads like so

    (__ \ "foo").read[String](minLength[String](5)).map(v => v.reverse)
    

    Here is a working example

    val json =
      """
        |{
        |  "foo": "abcdefghijkl",
        |  "bar": "012345678910"
        |}
        |""".stripMargin
    
    case class Test(foo: String, bar: String)
    
    val readsTest: Reads[Test] = (
      (__ \ "foo").read[String](minLength[String](5)).map(v => v.reverse)
      (__ \ "bar").read[String](minLength[String](10))
    )(Test.apply _)
    
    Json.parse(json).validate[Test](readsTest)
    

    which outputs

    JsSuccess(Test(lkjihgfedcba,012345678910),)