Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

possible to unmarshal generic subtypes? #203

@evbo

Description

@evbo

Hi,

Is it possible to unmarshall generic types? Here I've reproduced an example that fails to compile due to:

Error:(28, 88) could not find implicit value for parameter um: akka.http.scaladsl.unmarshalling.Unmarshaller[akka.http.scaladsl.model.HttpResponse,Requests.this.SomeResponse[T]]
val unmarshalled: Future[SomeResponse[T]] = response.flatMap(Unmarshal(_).to[SomeResponse[T]])

full REPL reproduction below. See comment:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.{HttpMethods, HttpRequest, HttpResponse, RequestEntity}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.ActorMaterializer
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.generic.auto._

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}


trait Requests extends FailFastCirceSupport {

  implicit val system = ActorSystem("testSystem")
  implicit val ec = system.dispatcher
  implicit val mat = ActorMaterializer()

  case class SomeRequest(query: String)
  case class SomeData[T](queryResponse: T)
  case class SomeResponse[T](data: SomeData[T])
  case class SampleData(hello: String)


  def parseContent[T <: SampleData](query: String) = {
    val response: Future[HttpResponse] = requestContent(SomeRequest(query))

// See Comment:
// This line wont compile unless I replace T with an explicit type like SampleData. 
// Why? Is it be possible to use T somehow?
    val unmarshalled: Future[SomeResponse[T]] = response.flatMap(Unmarshal(_).to[SomeResponse[T]])

    val hello: Future[String] = for {
      root <- unmarshalled
    } yield root.data.queryResponse.hello

    Await.result[String](hello, 30 seconds)
  }

  def requestContent(request: SomeRequest): Future[HttpResponse] = {
    for {
      request <- Marshal(request).to[RequestEntity]
      response <- Http().singleRequest(HttpRequest(
        method = HttpMethods.POST,
        uri = "http://localhost:8000/Some",
        entity = request
      ))
    } yield response
  }
}

object OtherRequests extends Requests {
  val query =
    """
        query GetSomething {
          results: getSomething() {
            hello
          }
        }
      """.replaceAll("//\\d+", "")

  def getSome() = {
    parseContent[SampleData](query)
  }
}

OtherRequests.getSome()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions