jsonscalajson4s

Serialization.read() is not "found" inside a map block [Scala]


I'm using json4s for dealing with Json responses from http responses. I was earlier using Await but I'm now switching to use Future.

I have a function like:

executeRequest(): Future[Response[String]]

and another function like:

def getAccessToken() = {
 executeRequest().map {
    response: Response[String] => // read method in the next line cannot be resolved
      read[AccessTokenResponse](response.body).access_token
   }
 // the following line is ok
 read[AccessTokenResponse]("{\"access_token\":\"fake_token\"}").access_token
}

Now, the read inside the map block is no longer recognized/found by my IntelliJ which I'm assuming means I'm doing something wrong. But the read outside of the map block resolves correctly.

What am I doing incorrectly here? I'm new to Scala :/

Compiler output:

overloaded method value read with alternatives:
  (in: java.io.Reader)(implicit formats: org.json4s.Formats, implicit mf: scala.reflect.Manifest[AccessTokenResponse])AccessTokenResponse <and>
  (json: org.json4s.JsonInput)(implicit formats: org.json4s.Formats, implicit mf: scala.reflect.Manifest[AccessTokenResponse])AccessTokenResponse <and>
  (json: String)(implicit formats: org.json4s.Formats, implicit mf: scala.reflect.Manifest[AccessTokenResponse])AccessTokenResponse
 cannot be applied to (Either[String,String])
      read[AccessTokenResponse](response.body).access_token

Solution

  • The error which you are getting means that the read method can accept an argument of one of these types:

    This line works because you are passing a String to read:

    read[AccessTokenResponse]("{\"access_token\":\"fake_token\"}").access_token
    

    However, as we can see from the error message, the response.body type is Either[String,String].

    Either is a sum type with two variants: Left and Right. Basically, that means that when a method returns Either[A, B], the actual result can be either A or B wrapped into Left or Right respectively.

    Either is often used to represent a result of an operation which can fail, where Left is returned in case of an error while Right contains the result of the operation in case of success. If this is the case, you might want to pattern match on the result to extract the value:

    executeRequest().map { response =>
      response.body match {
        case Right(body) =>
          read[AccessTokenResponse](body).access_token
        case Left(err) =>
          // Handle the error here
      }
    }