我的应用程序支持protobuf和JSON序列化。对于JSON序列化,我使用com.trueaccord.scalapb.json.JsonFormat
,我的dtos是从proto定义生成的。如何在Mashaller中使用http请求头进行内容协商?
com.trueaccord
序列化程序将选项类型包装为JSON对象,这对某些客户端造成了问题,所以我希望能够在不制动现有客户端的情况下支持org.json4s
。
我希望能挑到基于称为JFORMAT自定义HTTP标头中的序列化。这个想法是,如果这个头被发送,我会使用json4s,否则我会使用trueaccord序列化程序。
我成功地创建一个Unmarshaller的,可以挑根据报头值的请求序列化:
Unmarshaller.withMaterializer[HttpRequest, T](_ => implicit mat => {
case request: HttpRequest =>
val entity = request.entity
entity.dataBytes.runFold(ByteString.empty)(_ ++ _).map(data => {
entity.contentType match {
case `applicationJsonContentType` =>
val jsFormat = {
val header = request.headers.find(h => h.name() == jsonFormatHeaderName)
if (header.isEmpty) "1.0" else header.get.value()
}
val charBuffer = Unmarshaller.bestUnmarshallingCharsetFor(entity)
val jsonText = data.decodeString(charBuffer.nioCharset().name())
val dto = if(jsFormat == "2.0") {
write[T](value)(formats) // New Formatter
} else {
JsonFormat.fromJsonString[T](jsonText) // Old Formatter
}
dto
case `protobufContentType` =>
companion.parseFrom(CodedInputStream.newInstance(data.asByteBuffer)) // Proto Formatter
case _ =>
throw UnsupportedContentTypeException(applicationJsonContentType, protobufContentType)
}
})
我想要做同样与我的Marshaller我与Marshaller.oneOf和JSON处理一个使用看起来像:
Marshaller.withFixedContentType(contentType) { value =>
val jsonText = JsonSerializer.toJsonString[T](value)
HttpEntity(contentType, jsonText)
}
有没有办法构建一个Mashaller知道请求http头? Akka HTTP文档没有任何示例,我无法理解PredefinedToRequestMarshallers。
我需要多marshallers某种方式合并或者我可以请求序列我可以在以后的Marshaller使用过程中添加一些元数据的情况下?我想避免附加元到我的DTO如果可能的话,或使用自定义内容类型一样application/vnd.api+json
有很多其他有用的信息,当我格式化喜欢的Accept-Encoding响应我可以从使用请求,自定义标题一样独特请求ID创建一个相关ID,我可以通过读取callback
查询parmeter添加JSONP支持等
澄清:我需要通过创建它的解决方案中使用的Mashaller,子类或自定义版本工厂方法或多个链接在一起的Marshailer。 Marshaller.withFixedContentType
已经使用Accept
标题,所以必须有一个方法。我添加了赏金以奖励针对特定挑战的解决方案。我是黑客和变通办法的软件,我问了这个问题,因为我需要一个干净的解决方案来解决特定的场景。
我可能失去了一些东西:你为什么不实例化编组收到请求后,一旦你知道哪一个你需要什么? 解组所有内容类型的解组是有意义的,但编组几乎是将您的答案转换为任何您想要的,所以如果您希望它取决于请求,请将其作为请求的函数? – C4stor