2017-05-14 26 views
1


我对scala非常陌生,如果你能帮助我解决以下问题,我将不胜感激。
我使用akka-http发送http请求我想声明一个通用的发送请求方法,它将使用Unmarshall的http响应正文转换为泛型类型。
我应该如何施放Unmarshal回应给T?如何反编组用作方法返回值的泛型类型?

发送请求的实现:

 

    def sendRequest[T](requestMessage :HttpRequestMessage) :Future[T] = 
    { 

     val promise = Promise[HttpResponse]() 
     val request = requestMessage.request -> promise 

     queue.offer(request).flatMap { 
      case QueueOfferResult.Enqueued => promise.future.flatMap[AnyRef] { 
      response => { 
       response.entity.toStrict(FiniteDuration(3,"seconds")).flatMap { 
        strict => Unmarshal(strict.getData).to[T] 
       } 
       } 
      } 
     } 

    } 

回答

2

如果你看一看的Unmarshal object的代码,你可以看到,在to使用的类型参数有一定的约束 - 一个隐含的解组:

class Unmarshal[A](val value: A) { 
    /** 
    * Unmarshals the value to the given Type using the in-scope Unmarshaller. 
    */ 
    def to[B](implicit um: Unmarshaller[A, B], ec: ExecutionContext, mat: Materializer): Future[B] = um(value) 
} 

将类型A的值解组为类型B的值时,必须存在范围内可用的类型为Unmarshaller[A, B]的隐式值。有许多预定义的反编码器(例如here是一些常用的从String转换为各种类型的Int,Boolean等),但您也可以定义自己的。这被称为类型模式。

因此,如果您希望代码适用于某种类型的T,则必须确保该作用域中存在该类型的隐式解组器。这意味着您的方法sendRequest必须有一个Unmarshaller[Data, T]类型的隐式参数,其中Data应该替换为实际类型strict,getData(我无法从您的代码中知道)。

因此,像这样:

def sendRequest[T](requestMessage: HttpRequestMessage)(implicit m: Unmarshaller[Data, T]): Future[T] // replace Data with concrete type 

这样的to[T]编制,但现在你必须在to[T]调用点实际上在这个范围内含价值的义务。如前所述,您有两个选择 - 要么导入预定义的unmarshallers(如前面显示的PredefinedFromStringUnmarshallers),要么定义您自己的。我不知道什么T可以,所以我不能告诉你比这更进一步,但重点是只要你提供T后面的具体类型的解组器(通过导入或手动定义),它应该工作;否则阿卡将不知道如何解开你的T.

+0

谢谢:)你的解释确实帮助我取得了进展 –

+0

@Zfanya Leib很高兴听到这一点。因为你看起来很新,所以让我解释一下 - 理想情况下,每个问题都应该“最终确定”。这意味着由于某种原因应答或关闭。如果你得到了你需要的帮助,你应该接受最有用的答案,否则你可以编辑它并提供更多细节。没有被接受的答案的问题可能会吸引其他想尝试帮助你的人,如果你已经拥有了你需要的一切,这是浪费每个人的时间。当然,许多问题还没有得到解答,这就是为什么回答者应该被标记为这样。 – slouc