0
votes

I have a play controller REST end point that takes a json that I want to cast to the below case class in my Action.async case class MyData(id:Name, role:String)

I did some reading at https://www.playframework.com/documentation/2.6.x/ScalaBodyParsers I am still unclear how to use the syntax to cast the POST payload to my class. I am trying along the following lines but it is not compiling

Action.async(??) {??

}
3

3 Answers

0
votes

You can't just cast a body to whatever class you want, it doesn't work that way. If you want a body to return a class A, you need to follow https://www.playframework.com/documentation/2.6.x/ScalaBodyParsers#writing-a-custom-body-parser

That's a parser that turns a stream into A. But that's not a cast.

0
votes

You need Forms. https://www.playframework.com/documentation/2.6.x/ScalaForms So it will be something like this:

val form = Form(
  mapping(
    "id" -> text,
    "role" -> text
  )(MyData.apply)(MyData.unapply)
)

def action = Action.async { implicit request => 
form.bindFromRequest.fold(
  formWithErrors => {
    BadRequest("Error")
  },
  data => {
    //data is your case class mapped
    Ok("Success." + data.id + " " + data.role)
  }
)
}
0
votes

This should help you:

class MyController @Inject()(cc: ControllerComponents)
                            (implicit val ec: ExecutionContext) extends AbstractController(cc){

   def foo() = Action.async(cc.parsers.json) { implicit request =>
    request.body.validate[MyData].fold(
      errors => errorsToFutureResult(errors),
      myData => 
        //do staff with you data
        Ok(""))
    )
  }
}

And here is your case class definitions:

case class MyData(id:Name, role:String)
object MyData{
   implicit val myDataFormat: Format[MyData] = (
    (JsPath \ "id").format[Name] and
      (JsPath \ "role").format[String]
    ) (MyData.apply, unlift(MyData.unapply))
}