喷雾客户端 - 将具有意外内容类型的响应视为应用程序/json?
Posted
技术标签:
【中文标题】喷雾客户端 - 将具有意外内容类型的响应视为应用程序/json?【英文标题】:Spray client - treat response with unexpected content-type as application/json? 【发布时间】:2014-08-20 19:09:36 【问题描述】:当我尝试获取类似的亚马逊身份数据时
val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
使用适当的案例类和格式化程序,我收到以下异常
UnsupportedContentType(预期为“应用程序/json”)
因为亚马逊将他们的响应标记为 text/plain 内容类型。他们也不关心 Accept 标头参数。有没有一种简单的方法可以告诉 spray-json 在解组时忽略这一点?
【问题讨论】:
【参考方案1】:在挖掘了喷雾邮件列表后,我写了一个有效的函数
def mapTextPlainToApplicationJson: HttpResponse => HttpResponse =
case r@ HttpResponse(_, entity, _, _) =>
r.withEntity(entity.flatMap(amazonEntity => HttpEntity(ContentType(MediaTypes.`application/json`), amazonEntity.data)))
case x => x
在管道中使用它
val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> mapTextPlainToApplicationJson ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
很酷的是,只要您的拦截函数具有适当的签名,您就可以拦截和更改任何 HttpResponse。
【讨论】:
你的函数不用写,有mapHttpResponseEntity
指令
而且也不需要在HttpResponse实体上匹配并应用withEntity
,因为它会检查你的实体arg并在它不同时应用它(包括空实体案例),所以你可以简单做_.withEntity(..)
这个解决方案很好,但可以通过确保保留原始响应的HttpCharset
中的ContentType
来改进。将新的内容类型值设置为ContentType(MediaTypes.`applicaiton/json`, amazonEntity.contentType.charset)
【参考方案2】:
如果你想从亚马逊响应中提取一些IdentityData
(这是一个定义了jsonFormat
的案例类),这是一个有效的json,但是使用text/plain
上下文类型你可以简单地提取文本数据,解析它是一个 json 并转换为您的数据,例如:
entity.asString.parseJson.convertTo(identityDataJsonFormat)
【讨论】:
没想到这么简单。感谢您提醒检查简单选项:-) 经过数小时的挫折,这确实很有帮助。非常感谢!【参考方案3】:我想出了一个更简单/更简洁的@yevgeniy-mordovkin 解决方案版本。
def setContentType(mediaType: MediaType)(r: HttpResponse): HttpResponse =
r.withEntity(HttpEntity(ContentType(mediaType), r.entity.data))
用法:
val pipeline: HttpRequest => Future[IdentityData] = (
sendReceive
~> setContentType(MediaTypes.`application/json`)
~> unmarshal[IdentityData]
)
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
【讨论】:
这只有在制作人关心你的要求时才会起作用。就我而言,它没有。 我认为你误读了我的帖子。我和你做同样的事情(在收到响应后设置内容类型),只是代码更简洁一些。微小的改进,没有什么激进的。以上是关于喷雾客户端 - 将具有意外内容类型的响应视为应用程序/json?的主要内容,如果未能解决你的问题,请参考以下文章