无法从案例类中访问值

时间:2017-12-06 00:36:27

标签: json scala class http

我正在尝试使用sttp核心库和sttp json4s库来接收json响应并将其转换为case类。

Github上的源代码是 here ,我尝试复制的此示例的文档是 here

GET网址http://httpbin.org/get?foo=bar的{​​{1}}请求的响应如下:

{
  "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"
}

尝试读取上面的json响应的case类看起来像:

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

案例类已在测试文件的顶部定义,可供测试访问。

此测试通过:

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]
}

产生错误的代码如下所示:

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)
}

但是,当我尝试访问res.origin中的值时,我看到的错误是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

1 个答案:

答案 0 :(得分:0)

Rob Norris on the gitter scala channel回答了这个问题:

  

折叠Either时,结果为Serializable。尝试模式匹配,或折叠到sys.error而不是String。

  1. 结果上的模式匹配:

    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. 将左侧折叠为sys.error而不是字符串,在这种情况下不需要模式匹配:

    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      
    
  3. 这两种方法中的任何一种都可以解决问题。