Scala中的通用REST客户端

时间:2016-02-29 18:12:45

标签: scala generics akka-http play-json

我对Scala有点新意,我正在尝试为我想使用的RESTful api编写通用客户端。我能够为我想要实例化我的客户端的特定案例类提供具体的Reads[T]Writes[T],但是编译器期望找到Reads[T]和{{1对于任何类型,不仅仅是我使用的类型。一些代码来说明(我省略了不相关的部分):

我的通用客户:

Writes[T]

JsonSupprt Trait:

class RestModule[T](resource: String, config: Config) ... with JsonSupport{
...
def create(item: T): Future[T] = {
    val appId = config.apiId
    val path = f"/$apiVersion%s/applications/$appId%s/$resource"

    Future {
      val itemJson = Json.toJson(item)
      itemJson.toString.getBytes
    } flatMap {
      post(path, _)
    } flatMap { response =>
      val status = response.status
      val contentType = response.entity.contentType

      status match {
        case Created => contentType match {
          case ContentTypes.`application/json` => {
            Unmarshal(response.entity).to[T]
          }
          case _ => Future.failed(new IOException(f"Wrong Content Type: $contentType"))
        }
        case _ => Future.failed(new IOException(f"HTTP Error: $status"))
      }
    }
...
}

我只是实例化为trait JsonSupport { implicit val accountFormat = Json.format[Account] } ,但我收到了错误

RestModule[Account]("accounts",config)

当T只能是Account类型时,为什么编译器认为它需要一个类型为T的Writes?有什么方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

编译器不喜欢你正在做的事情的原因是如何解决implicit参数的解决方法,更重要的是解决 的问题。< / p>

考虑一下代码段,

Object MyFunc {
   def test()(implicit s: String): String = s
}

implicit参数仅在调用函数时由参数解析,并且基本上被扩展为,

MyFunc.test()(resolvedImplicit)

在您的特定情况下,您实际上调用了需要implicit的函数,因此它会在该时间点查找implicit T。由于它无法在范围内找到一个,因此无法编译。

要解决此问题,只需将implicit参数添加到create方法,即告知编译器在您调用create而不是toJson时解析它create

此外,我们可以使用scala的隐式规则来获取您想要的行为。

让我们抓住你的特质Reads

trait Reads[A] {
}

object MyFunc {
  def create[A](a: A)(implicit reads: Reads[A]): Unit = ???
}

正如我们所说的那样,如果implicit在范围内,你可以调用它。但是,在这种具有预定义读取的特定情况下,我们实际上可以将它放在伴随对象中,

object Reads {
  implicit val readsInt: Reads[Int] = ???
  implicit val readsString: Reads[String] = ???
}

通过这种方式调用create时,如果implicitvals,则用户无需导入或定义任何A IntString因为如果scala无法在当前范围内找到任何隐式定义,scala会自动在随播对象中查找。