1

首先让我说我对 akka-http 很陌生,我所读的书都没有很好地涵盖编组主题。所以这对我来说有点像黑匣子。我能够获得以下 (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吗?如果是这样,它应该有什么?

4

1 回答 1

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))*/
    }
  }

即使这样,我也不知道如何同时启用两个解码器。所以我评论了一个。

于 2016-11-08T02:07:10.237 回答