【问题标题】:Extract specific JSON field with Scala and Argonaut使用 Scala 和 Argonaut 提取特定的 JSON 字段
【发布时间】:2015-01-29 12:26:59
【问题描述】:

我正在尝试使用 Scala 和 Argonaut 解析 json。

假设我从另一端 REST 服务获得 JSON 响应,但我不知道该响应中 json 字段的顺序和字段数。例如,http://headers.jsontest.com/ 返回带有五个字段的 JSON,但我只想提取一个字段并删除其他字段:

{
   "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
   "Host": "headers.jsontest.com",
   "Referer": "http://www.jsontest.com/",
   "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.4.0",
   "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}

所以我正在写一些代码:

object Service {

  case class Address(headers: String, rest: Option[String])

  implicit def AddressCodecJson: CodecJson[Address] =
    casecodec2(Address.apply, Address.unapply)("headers", "rest")

  def parse(data: String): Option[Address] = {
    Parse.decodeOption[Address](data)
  }

  def main(args: Array[String]): Unit = {
    val src = url("http://headers.jsontest.com/")
    val response: Future[String] = Http(src OK as.String)

    response onComplete {
      case Success(content) => {
        val userData: Option[Address] = parse(content)
        println(s"Extracted IP address = ${userData.get.headers}")
      }
      case Failure(err) => {
        println(s"Error: ${err.getMessage}")
      }
    }
  }
}

但当然这段代码不起作用,可能是因为来自 jsontest 的答案无法与 Address 案例类进行比较。

我收到此错误消息:

java.util.NoSuchElementException: None.get
    at scala.None$.get(Option.scala:313)
    at scala.None$.get(Option.scala:311)
    at micro.api.Service$$anonfun$main$1.apply(Service.scala:26)
    at micro.api.Service$$anonfun$main$1.apply(Service.scala:23)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
    at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.pollAndExecAll(ForkJoinPool.java:1253)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1346)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

我怎样才能只获得一个由其名称指定的字段?

【问题讨论】:

  • 请告诉我们content里面有什么。
  • 我用println(content)替换这行: val userData: Option[Address] = parse(content) println(s"Extracted IP address = ${userData.get.headers}") 并得到: { "Host": "headers.jsontest.com", "User-Agent": "Dispatch/0.11.1-SNAPSHOT", "Accept": "/" }

标签: json scala argonaut


【解决方案1】:

您的代码有:

implicit def AddressCodecJson: CodecJson[Address] =
  casecodec2(Address.apply, Address.unapply)("headers", "rest")

你说:

我将这行:val userData: Option[Address] = parse(content) println(s"Extracted IP address = ${userData.get.headers}") 替换为 println(content) 并得到:{ "Host": "headers.jsontest.com", "User-Agent": "Dispatch/0.11.1-SNAPSHOT", "Accept": "/" }

所以你得到的回应是:

{ "Host": "headers.jsontest.com", "User-Agent": "Dispatch/0.11.1-SNAPSHOT", "Accept": "/" }

你正在像这样解码它:

Parse.decodeOption[UserData](data).get

...这意味着您非常肯定且非常明显地收回了None

——现在你为什么期望从不包含预期的headersrest 属性的JSON 字典中得到一个非None 值?

(我假设您知道在拥有 None 值的 Option[T] 上调用 .get 会引发异常。)

附:我不确定地址与 HTTP 标头有什么关系...?只是说......从建模的角度来看。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    • 2021-11-09
    • 2017-01-06
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    相关资源
    最近更新 更多