0

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

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

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

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

找不到 spray.httpx.unmarshalling.FromResponseUnmarshaller[spray.json.JsValue] 类型的证据参数的隐式值

根格式也出错。

我不知道如何完成我需要的,任何帮助将不胜感激。

4

2 回答 2

1

使用Either,埃里克!:) 如果响应将是 JsObject 或 JsArray 那么Either是一个很好的解决方案。

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

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

于 2016-01-25T08:57:01.067 回答
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 我很想听听你的想法。

于 2016-01-25T15:18:57.200 回答