json - Spray-Json:如何解析Json阵列?

标签 json scala spray-json

我是Spray-Json API的新手,并且试图解析Docker REST API的Json响应。

There是使用Spray-Json解析此Google Map Json响应的一个干净示例:

{
   "results" : [
      {
         "elevation" : 8815.7158203125,
         "location" : {
            "lat" : 27.988056,
            "lng" : 86.92527800000001
         },
         "resolution" : 152.7032318115234
      }
   ],
   "status" : "OK"
}

在上面的示例中,最外层是Object。但是,我需要直接解析一个Json响应,其最外层是一个由容器信息组成的Array,如下所示:
[
     {
       "Id": "8dfafdbc3a40",
       "Image": "base:latest",
       "Command": "echo 1",
       "Created": 1367854155,
       "Status": "Exit 0",
       "Ports":[{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
       "SizeRw":12288,
       "SizeRootFs":0
     },
     { ... },
     { ... }
]

这是我从Google map 示例改编而成的代码:
package main

import ...

case class Container(id: String, image: String, command: String, created: Long, status: String, ports: List[Port], sizeRW: Long, sizeRootFs: Long)
case class Port(privatePort: Long, publicPort: Long, portType: String)
case class DockerApiResult[T](results: List[T])

object ContainerListJsonProtocol extends DefaultJsonProtocol {
  implicit val portFormat = jsonFormat3(Port)
  implicit val containerFormat = jsonFormat8(Container)
  implicit def dockerApiResultFormat[T :JsonFormat] = jsonFormat1(DockerApiResult.apply[T])
}

object Main extends App {

  implicit val system = ActorSystem("simple-spray-client")
  import system.dispatcher // execution context for futures below
  val log = Logging(system, getClass)

  log.info("Requesting containers info...")

  import ContainerListJsonProtocol._
  import SprayJsonSupport._
  val pipeline = sendReceive ~> unmarshal[DockerApiResult[Container]]

  val responseFuture = pipeline {
    Get("http://<ip-address>:4243/containers/json")
  }

  responseFuture onComplete {
    case Success(DockerApiResult(Container(_,_,_,_,_,_,_,_) :: _)) =>
      log.info("Id of the found image: {} ")
      shutdown()

    case Success(somethingUnexpected) =>
      log.warning("The Docker API call was successful but returned something unexpected: '{}'.", somethingUnexpected)
      shutdown()

    case Failure(error) =>
      log.error(error, "Couldn't get containers information")
      shutdown()
  }

  def shutdown(): Unit = {
    IO(Http).ask(Http.CloseAll)(1.second).await
    system.shutdown()
  }
}

下面是我得到的异常(Object expected):
spray.httpx.PipelineException: MalformedContent(Object expected,Some(spray.json.DeserializationException: Object expected))

我当然会错过一些显而易见的事情,但是如何使用Spray-Json解析Json数组?

另外,是否有一种简单的方法可以执行此操作而不必处理自定义JsonFormat或RootJsonFormat?

最佳答案

通过执行unmarshal[DockerApiResult[Container]],您告诉Spray-json您希望格式为以下形式的json对象:

{ results: [...] }

因为case class DockerApiResult[T](results: List[T])被定义为具有包含列表的单个结果字段的对象。

相反,您需要执行以下操作:
unmarshal[List[Container]]

然后直接对结果列表进行操作(或在通过spray-json对其进行解析后将其包装在DockerApiResult中)。

如果您想将spray-json直接解码到DockerApiResult中,则可以编写具有以下内容的JsonFormat:
implicit object DockerApiResultFormat extends RootJsonFormat[DockerApiResult] {
  def read(value: JsValue) = DockerApiResult(value.convertTo[List[Container]])
  def write(obj: DockerApiResult) = obj.results.toJson
}

关于json - Spray-Json:如何解析Json阵列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20523462/

相关文章:

java - Jackson Mapper 未反序列化 JSON -(无法读取 JSON : Already had POJO for id (java. lang.Integer))

scala - 如何在 Linux 上从 Scala 代码运行导出命令来添加新的环境变量?

Scala 反序列化 : class not found

json - 在 Spray 1.2.0 路由中将查询字符串参数与 JSON 实体相结合

scala - 使用特殊字符喷射 json 属性

json - 新行输出 CloudFormation Json 模板

javascript - RESTful JSON 端点应该以 .js 结尾吗? JSONP 怎么样?

ios - Int64 不工作,而 Int 工作

java - 在 Play 2.5.x 中找不到类 play.api.cache.CacheApi 的构造函数

scala - 喷雾客户端 - 将具有意外内容类型的响应视为应用程序/json?