使用 Scala 和 Argonaut 提取特定的 JSON 字段
Extract specific JSON field with Scala and Argonaut
我正在尝试使用 Scala 和 Argonaut 解析 json。
假设我从另一方 REST 服务收到 JSON 响应,但我不知道该响应中 json 字段的顺序和字段数。例如,http://headers.jsontest.com/ returns 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
case class.
不相比较
我收到此错误消息:
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.apply(Service.scala:26)
at micro.api.Service$$anonfun$main.apply(Service.scala:23)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$$anon.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)
如何才能只获取一个指定字段的名称?
您的代码有:
implicit def AddressCodecJson: CodecJson[Address] =
casecodec2(Address.apply, Address.unapply)("headers", "rest")
你说:
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": "/" }
所以您的回复是:
{ "Host": "headers.jsontest.com", "User-Agent": "Dispatch/0.11.1-SNAPSHOT", "Accept": "/" }
而你是这样解码的:
Parse.decodeOption[UserData](data).get
...这意味着您非常肯定并且非常明显地得到了 None
.
— 现在为什么您期望从不包含预期的 headers
和 rest
属性的 JSON 字典中获取非 None
值?
(我假设您知道在包含 None
值的 Option[T]
上调用 .get
会引发异常。)
P.S。我不确定地址与 HTTP headers 有什么关系...?只是说...从建模的角度来看。
我正在尝试使用 Scala 和 Argonaut 解析 json。
假设我从另一方 REST 服务收到 JSON 响应,但我不知道该响应中 json 字段的顺序和字段数。例如,http://headers.jsontest.com/ returns 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
case class.
我收到此错误消息:
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.apply(Service.scala:26)
at micro.api.Service$$anonfun$main.apply(Service.scala:23)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$$anon.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)
如何才能只获取一个指定字段的名称?
您的代码有:
implicit def AddressCodecJson: CodecJson[Address] =
casecodec2(Address.apply, Address.unapply)("headers", "rest")
你说:
I replace this lines:
val userData: Option[Address] = parse(content) println(s"Extracted IP address = ${userData.get.headers}")
withprintln(content)
and get:{ "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
.
— 现在为什么您期望从不包含预期的 headers
和 rest
属性的 JSON 字典中获取非 None
值?
(我假设您知道在包含 None
值的 Option[T]
上调用 .get
会引发异常。)
P.S。我不确定地址与 HTTP headers 有什么关系...?只是说...从建模的角度来看。