Spray:如何在管道中解组 JsArray 或 JsObject(即 JsValue)的响应

Spray : How to Unmarshal a response of JsArray or JsObject (ie JsValue) in pipeline

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

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

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

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

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

的证据参数的隐式值

而且根格式也有错误。

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

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

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

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

在查看@Mustafa 的回答后,我创建了以下内容以避免潜在的性能影响。最后真的只需要一个JSON AST就可以传下去了

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

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

并修改如下:

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

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