Spray:如何在管道

时间:2016-01-24 15:02:13

标签: spray spray-json spray-client spray-dsl

我正在创建一个聚合数据的服务,并且需要能够读取任何未知的JSON文档。我的管道定义如下:

  private def pipeline = (
       addHeader("Accept", "application/json")
    ~> sendReceive
    ~> unmarshal[JsObject] // Need this to work for JsObject or JsArray //
    ~> recover
  )

这适用于JsObject但不适用于JsArray。如果我将其更改为JsArray,那么它(当然)不会使用JsObject。我的recover方法返回一个JsObject。

我希望能够将其定义为JsValue或强制执行Root格式,但对于JsValue,我得到以下编译器错误:

找不到类型为spray.httpx.unmarshalling.FromResponseUnmarshaller [spray.json.JsValue]

的证据参数的隐含值

Root Formats也出错了。

我不确定如何完成我需要的任何帮助,我们将不胜感激。

2 个答案:

答案 0 :(得分:1)

使用Either,Eric! :)如果响应是JsObject或JsArray,那么Either是很好的解决方案。

private def pipeline =
       addHeader("Accept", "application/json")
    ~> sendReceive
    ~> unmarshal[Either[JsObject, JsArray]]
    ~> recover

但是,请注意unmarshal[Either[JsObject, JsArray]]首先尝试将响应解析为JsObject,如果失败,请尝试将其解析为JsArray。这可能会导致一些性能问题。

答案 1 :(得分:1)

在回顾@ Mustafa的回答之后,我创建了以下内容以避免潜在的性能损失。最后,我真的只需要传递JSON AST。

用最简单的术语来说,我只是创建了一个处理它的函数:

  def unmarshalJSON(httpResponse: HttpResponse): JsValue = {
    httpResponse.entity.asString.parseJson
  }

并在下面进行了修改:

private def pipeline = {
     addHeader("Accept", "application/json")
  ~> sendReceive
  ~> unmarshalJSON
  ~> recover
}

我当然希望为生产级别代码加强一点,但这可能是另一种选择,并允许我返回一个JsValue。 @Mustafa我很想听听你的想法。