简体   繁体   English

使用Scala和Argonaut提取特定的JSON字段

[英]Extract specific JSON field with Scala and Argonaut

I'm trying to parse json with Scala and Argonaut. 我正在尝试使用Scala和Argonaut解析json。

Suppose I get JSON response from other side REST service and I don't know order of json's fields in that response and the number of fields. 假设我从其他REST服务获得JSON响应,但我不知道该响应中JSON字段的顺序和字段数。 For example, http://headers.jsontest.com/ returns JSON with five fields, but I want to extract only one field and drop others: 例如, 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"
}

So I'm write some code: 所以我写一些代码:

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

But of course this code doesn't work, probably because answers from jsontest doesn't compare with Address case class. 但是当然,此代码不起作用,可能是因为jsontest的答案无法与Address case类进行比较。

I get this error message: 我收到此错误消息:

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)

How can I get only one field specified by its name? 如何仅获得由其名称指定的一个字段?

Your code has: 您的代码具有:

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

and you said: 你说:

I replace this lines: val userData: Option[Address] = parse(content) println(s"Extracted IP address = ${userData.get.headers}") with println(content) and get: { "Host": "headers.jsontest.com", "User-Agent": "Dispatch/0.11.1-SNAPSHOT", "Accept": "/" } 我替换以下行: 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": "/" }

so the response you have is: 所以您的回应是:

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

and you're decoding it like this: 并且您正在像这样解码它:

Parse.decodeOption[UserData](data).get

...which means you're quite certainly and quite obviously getting back a None . ...这意味着您肯定会并且很显然会返回None

— now why would you be expecting to get a non- None value out of a JSON dictionary that does not contain the expected headers and rest attributes? —现在为什么要期望从不包含期望的headersrest属性的JSON字典中获得非None值?

(I'm presuming you know that calling .get on an Option[T] that holds a None value throws an exception.) (我假设您知道对拥有None值的Option[T]调用.get会引发异常。)

PS I'm not sure what's an address got to do with HTTP headers...? PS我不确定与HTTP标头有什么关系...? Just sayin'... from a modelling point of view. 从建模的角度说...。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM