我正在创建一个聚合数据的服务,并且需要能够读取任何未知的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也出错了。
我不确定如何完成我需要的任何帮助,我们将不胜感激。
答案 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我很想听听你的想法。