【问题标题】:Generic return type in scala with akka marshalling带有akka编组的scala中的通用返回类型
【发布时间】:2018-04-29 16:20:17
【问题描述】:

我有以下相当简单的代码:

case class InverterResponse(body: InverterBody) extends SolarResponse
case class InverterBody(data: InverterData)
case class InverterData(dayEnergy: DayEnergy)
case class DayEnergy(unit: String, values: Values)
case class Values(value: Int)

case class MeterResponse(body: MeterBody) extends SolarResponse
case class MeterBody(data: MeterData)
case class MeterData(powerRealSum: BigDecimal, powerRealPhase1: BigDecimal, powerRealPhase2: BigDecimal, powerRealPhase3: BigDecimal)

class SolarWebConnector extends JsonSupport {
  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()

  val httpClient = Http().outgoingConnection(host = "192.168.178.22", port = 80)

  def getInverterRealtimeData(): InverterData = {
    val inverterRealtimeURLPath = s"""/solar_api/v1/GetInverterRealtimeData.cgi?scope=System"""
    val flowGet: Future[InverterResponse] = sendRequest[InverterResponse](inverterRealtimeURLPath)
    val start = System.currentTimeMillis()
    val result = Await.result(flowGet, 5 seconds)
    val end = System.currentTimeMillis()
    println(s"Result in ${end - start} millis: $result")
    result.body.data
  }

  private def sendRequest[T](inverterRealtimeURLPath: String) : Future[T] = {
    val flowGet: Future[T] =
      Source.single(
        HttpRequest(
          method = HttpMethods.GET,
          uri = Uri(inverterRealtimeURLPath))
      )
        .via(httpClient)
        .mapAsync(1)(response => Unmarshal(response.entity).to[T])
        .runWith(Sink.head)
    flowGet
  }

  def getMeterRealtimeData(): String = {
    "test"
  }
}

JsonSupport 包含 json 格式定义,用于将传入的 json 编组到响应案例类。只要我不尝试为可以返回 InverterResponse 或 MeterResponse 类型的 sendRequest 方法定义通用版本,这就可以正常工作。它编译得很好,但我得到了:

Error:(54, 63) Play 2 Compiler: 
 /Users/tbecker/workspaces/home-integrator/app/services/SolarWebConnector.scala:54:63: could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.Unmarshaller[akka.http.scaladsl.model.ResponseEntity,T]
         .mapAsync(1)(response => Unmarshal(response.entity).to[T])
                                                               ^

大约 2 年没有真正使用 scala...所以我的知识可能有点生锈...

【问题讨论】:

    标签: json scala generics akka spray


    【解决方案1】:

    通过在源代码和文档中挖掘自己找到了答案。

    https://doc.akka.io/docs/akka-http/current/scala/http/common/unmarshalling.html

    https://github.com/akka/akka-http/blob/v10.0.3/akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/Unmarshal.scala

    Umarshall 需要一个隐式的 Unmarshaller。像这样在方法签名中提供它可以解决问题:

    private def sendRequest[T](inverterRealtimeURLPath: String)(隐式 m: Unmarshaller[ResponseEntity, T]) : Future[T] = {

    【讨论】:

    • 请注意,隐式解组器现在称为um 而不是m
    猜你喜欢
    • 1970-01-01
    • 2015-12-28
    • 2019-03-29
    • 1970-01-01
    • 2011-02-14
    • 2020-07-19
    • 1970-01-01
    • 2021-01-26
    • 2011-05-11
    相关资源
    最近更新 更多