Home Cannot access value from case class
Reply: 1

Cannot access value from case class

vamsiampolu
1#
vamsiampolu Published in 2017-12-06 00:36:26Z

I am trying to use the sttp core library along with the sttp json4s library in order to receive a json response and convert it to a case class.

The source code on Github is here and the documentation for this example that I am trying to replicate is here

The response to the GET request to the URL http://httpbin.org/get?foo=bar looks like:

{
  "args": {
    "foo": "bar"
  }, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", 
    "Accept-Encoding": "gzip,deflate", 
    "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8", 
    "Connection": "close", 
    "Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1; stale_after=never", 
    "Forwarded": "for=49.255.235.138", 
    "Host": "httpbin.org", 
    "Save-Data": "on", 
    "Scheme": "http", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
  }, 
  "origin": "49.255.235.138, 66.249.82.79", 
  "url": "http://httpbin.org/get?foo=bar"
}

The case class which attempts to read the json response above looks like:

case class HttpBinResponse(
  args: Map[String, String],
  origin: String,
  headers: Map[String,String]
)

The case class has been defined at the top of the test file and is accessible to the test.

This test passes:

it should "send a GET request parse response as JSON" in {
  implicit val backend = HttpURLConnectionBackend()
  val queryParams = Map("foo" -> "bar", "bugs" -> "life")

  val endpoint:Uri = uri"http://httpbin.org/get?foo=bar"

  val request = sttp
    .get(endpoint)
    .response(asJson[HttpBinResponse])

  val response = request.send()
  // response.body is an Either

  response.code should be(200)
  val res = response.body.fold(_ => { "Error" }, a => { a })

  res shouldBe a[HttpBinResponse]
}

The code that produces the error looks like this:

it should "send a GET request parse response as JSON" in {
  implicit val backend = HttpURLConnectionBackend()

  val queryParams = Map("foo" -> "bar", "bugs" -> "life")

  val endpoint:Uri = uri"http://httpbin.org/get?foo=bar"

  val request = sttp
    .get(endpoint)
    .response(asJson[HttpBinResponse])

  val response = request.send()
  // response.body is an Either

  response.code should be(200)
  val res = response.body.fold(_ => { "Error" }, a => { a })

  res shouldBe a[HttpBinResponse]
  println(res.origin)
}

However, when I try and access a value from the res.origin, I see the error that is value origin is not a member of java.io.Serializable

28. Waiting for source changes... (press enter to interrupt)
[info] Compiling 1 Scala source to /Users/localuser/Do/scalaexercises/target/scala-2.12/test-classes...
[error] /Users/localuser/Do/scalaexercises/src/test/scala/example/SttpSpec.scala:58: value origin is not a member of java.io.Serializable
[error]     println(res.origin)
[error]                 ^
[error] one error found
[error] (test:compileIncremental) Compilation failed
stefanobaghino
2#
stefanobaghino Reply to 2017-12-06 06:32:23Z

The question was answered by Rob Norris on the gitter scala channel as:

When you fold the Either the result is Serializable. Try pattern matching on it, or fold to sys.error instead of String.

  1. Pattern Matching on the result:

    val res = response.body.fold(_ => { "Error" }, a => { a })
    res match {
      case HttpBinResponse(_, origin) => {
        println("-----------------------------")
        print("The origin for the request is ")
        print(origin)
        println("-----------------------------")
      }
      case _ => "Error"
    }
    
  2. fold the Left to sys.error instead of String, no pattern matching needed in this case:

    val res = response.body.fold(
      _ => { error("Error") },
      a => { a }
    )
    println(res.origin)
    res.args should contain("foo" -> "bar")
    res.args should contain key("bugs")
    res.args should contain value("life")
    res.origin.length should be >10      
    

Either of these two approaches would solve the issue.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.299331 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO