首先我要说的是,我对akka-http非常新,没有一本书能够很好地涵盖marsheling主题。所以对我来说这是一个黑盒子。我能够获得以下(Un)Marsheller,它能够根据请求头返回json和protobuf。
这部分代码工作正常,我有一个在akka-http中定义的get路由,它工作正常。
trait PBMarshaller {
private val protobufContentType = ContentType(MediaType.applicationBinary("octet-stream", Compressible, "proto"))
private val applicationJsonContentType = ContentTypes.`application/json`
implicit def PBFromRequestUnmarshaller[T <: GeneratedMessage with Message[T]](companion: GeneratedMessageCompanion[T]): FromEntityUnmarshaller[T] = {
Unmarshaller.withMaterializer[HttpEntity, T](_ => implicit mat => {
case entity@HttpEntity.Strict(`applicationJsonContentType`, data) =>
val charBuffer = Unmarshaller.bestUnmarshallingCharsetFor(entity)
FastFuture.successful(JsonFormat.fromJsonString(data.decodeString(charBuffer.nioCharset().name()))(companion))
case entity@HttpEntity.Strict(`protobufContentType`, data) =>
FastFuture.successful(companion.parseFrom(CodedInputStream.newInstance(data.asByteBuffer)))
case entity =>
Future.failed(UnsupportedContentTypeException(applicationJsonContentType, protobufContentType))
})
}
implicit def PBToEntityMarshaller[T <: GeneratedMessage]: ToEntityMarshaller[T] = {
def jsonMarshaller(): ToEntityMarshaller[T] = {
val contentType = applicationJsonContentType
Marshaller.withFixedContentType(contentType) { value =>
HttpEntity(contentType, JsonFormat.toJsonString(value))
}
}
def protobufMarshaller(): ToEntityMarshaller[T] = {
Marshaller.withFixedContentType(protobufContentType) { value =>
HttpEntity(protobufContentType, value.toByteArray)
}
}
Marshaller.oneOf(protobufMarshaller(), jsonMarshaller())
}
}
我面临的问题是在邮政路线上。
(post & entity(as[PropertyEntity])) { propertyEntity =>
complete {
saveProperty(propertyEntity)
}
}
在编译期间,我收到以下错误
Error:(20, 24) could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller[PropertyEntity]
(post & entity(as[PropertyEntity])) { propertyEntity =>
我不确定我到底错过了什么。我需要定义implicit FromRequestUnmarshaller
吗?如果是的话应该有什么?
答案 0 :(得分:0)
我能够一起破解可以工作的东西,但我仍然不知道如何创建一个可以解码任何ScalaPB案例类的通用Unmarshaller
implicit val um:Unmarshaller[HttpEntity, PropertyEntity] = {
Unmarshaller.byteStringUnmarshaller.mapWithCharset { (data, charset) =>
val charBuffer = Unmarshaller.bestUnmarshallingCharsetFor(data)
JsonFormat.fromJsonString(data.decodeString(charBuffer.nioCharset().name()))(PropertyEntity)
/*PropertyEntity.parseFrom(CodedInputStream.newInstance(data.asByteBuffer))*/
}
}
即便如此,我也不知道如何同时启用两个解码器。所以我评论了一个。