2016-04-08 10 views
1

Scalaのジェネリックスを使用しています私は自分のPlayアプリケーションでいくつかの一般的な関数を抽象化しようとしています。この関数は、REST JSONサービスから直列化解除されたオブジェクトを持つSeqを返します。Scala関数の戻り値の型はgenericに基づいています

def getPeople(cityName: String): Future[Seq[People]] = { 
    getByEndpoint[People](s"http://localhost/person/$cityName") 
} 

def getPeople(): Future[Seq[Dog]] = { 
    getByEndpoint[Dog]("http://localhost/doge") 
} 

フェッチおよびデシリアライズロジックは、ジェネリックを使用して1つの関数にパックされています。

private def getByEndpoint[T](endpoint: String): Future[Seq[T]] = { 

    ws.url(endpoint) 
     .get() 
     .map(rsp => rsp.json) 
     .flatMap { json => 
     json.validate[Seq[T]] match { 
      case s: JsSuccess[Seq[T]] => 
      Future.successful(s.get) 
      case e: JsError => 
      Future.failed(new RuntimeException(s"Get by endpoint JSON match failed: $e")) 
     } 
     } 

} 

問題がある、私は "No Json deserializer found for type Seq[T]. Try to implement an implicit Reads or Format for this type." を取得しています。私はを適切にSeq[T](私のC#/ Javaの記憶によれば)で正しく使用していないと確信していますが、Scalaで適切な方法を実行する方法を見つけることができません。ジェネリックを使わずにすべてが期待どおりに機能します。

+1

'def getByEndpoint [T]'を 'def getByEndpoint [T:Format]'に変更しようとしていますか?それがうまくいくなら、私は理由を説明する答えを書いてうれしいです。 –

+0

ありません!私が推測しているのは、モデルに設定した 'Json.format'と関係があることです。私は答えとしてマークすることができますので、返信を投稿していただけますか? – giannoug

答えて

2

再生JSONは、type classesを使用して、JSONとの間で(非)シリアライズ可能な情報とその方法を取得します。スコープ内にタイプFormat[Foo]の暗黙の値がある場合は、それはFooFormatタイプクラスのインスタンスと呼ばれます。

このアプローチの利点は、サブタイプに依存しないジェネリック型を制約する(コンパイル時にこれらの制約をチェックする)ことができます。たとえば、標準ライブラリのStringは、Play(または他のライブラリ)が提供する可能性のある種類のJsonableの種類を拡張する方法はないため、「StringをJSONとしてエンコードする方法を知っています」という言い方が必要です。 Stringを我々が定義したいくつかの形質のサブタイプにすることを含む。

あなたが暗黙の Formatインスタンスを定義することによって、これを行うと、あなたのためにこれらの多くを提供して自分自身を再生することができますプレイJSONで

(あなたがTのための1つを持っている場合例えば、それはあなたにSeq[T]のための1つを与えるでしょう)。 JsValuevalidateメソッドでは、型パラメータ-の場合、これらのインスタンスの1つ(実際にはサブタイプはFormat,Readsですが、ここではあまり関係ありません)が必要で、コンパイラがそのインスタンスを見つけることができない限りコンパイルされません。

あなたがあなた自身の一般的な方法に制約を加えることで、このインスタンスを提供することができます。

private def getByEndpoint[T: Format](endpoint: String): Future[Seq[T]] = { 
    ... 
} 

今すぐあなたもかかわらず、あなたドン(TためFormatインスタンスが存在しなければならないことを指定したT: Format構文で他の方法ではTという制約があるため)、呼び出しに必要なSeq[T]のインスタンスをFormatインスタンスに提供する方法をコンパイラが知っています。

関連する問題