1

I'm a bit new to Scala I'm trying to convert the code block starting from if... which looks like Java to something more Scala like (I think a flatmap or case) but I was unable to create the correct result for the function. Any ideas? Thanks

override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] = {
def parseResponse(body: JsValue): Option[User] = body.asOpt[User]

if(request.headers.keys.contains("user")) {
  val jsonObject: JsValue = Json.parse(request.headers.get("user").get)
  val userOptional: Option[User] = parseResponse(jsonObject)
  Future.successful(userOptional)
} else {
  Future.successful(None)
}
}
2
  • 1
    that is totally fine to use if and else nothing wrong with this code? why do you want to use case for a trivial match? using match case in place of if and else is not the sacla way or something if you will see in scala library itself they have lots of if and else it's just you need to right pure function. Commented Mar 9, 2020 at 13:43
  • Is this Play? If so, one thing to keep in mind is, unfortunately Play was designed in a very OO way. If you want to go purely functional, you might want to switch to something like http4s. In terms of making this more "scala", see if you can get the contains to return an option
    – sinanspd
    Commented Mar 9, 2020 at 13:48

2 Answers 2

1
Future.successful(request.headers.get("user").flatMap { value =>
      val jsonObject: JsValue = Json.parse(value)
      val userOptional: Option[User] = parseResponse(jsonObject)
      userOptional
    })
0
1

The conversion from request to User involves three levels of optionality (or "missingness"):

  1. the "user" header could be missing,
  2. the header value could be invalid JSON,
  3. the JSON could not have the right shape to be deserialized into a User.

This multi-level optionality can be elegantly handled with a for-compehension, which will result in None if something is missing at any level, and in Some(user) if everything is good:

def userFromRequest(request: AuthenticatedRequest[A]): Option[User] =
  for {
    userHeader <- request.headers.get("user")  // "user" header may be missing 
    userJson   <- Json.parseOpt(userHeader)    // header value may be not valid json
    user       <- userJson.asOpt[User]         // json may be not convertible to user
  } yield user

Note that I have taken out the Future from the logic, since this conversion has nothing to do with asynchronous calls.

Then, you can implement the getSubject method by calling the function above:

override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] =
  Future.successful(userFromRequest(request))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.