2017-02-07 3 views
1

私はScalaの初心者で、他の人のコードを拡張しています。このコードでは、PlayフレームワークのJSONライブラリを使用しています。私はクラスFuture[Option[A]]Future[Option[List[B]]のオブジェクトにアクセスしています。 AクラスとBクラスはそれぞれ独自のJSON writesメソッドを持っているので、それぞれがWebリクエストに対する応答としてJSONを返すことができます。私はHTTP応答として返すことができる単一のJSON応答にこれらを組み合わせようとしています。Playフレームワークで複合クラスの複合グループからJSON出力を作成する方法

私は、単一のクラスへABを構成するクラスを作成すると、私はこれを行うことができるようになると思ったこれらの線に沿って何か:

case class AAndB(a: Future[Option[A]], b: Future[Option[List[B]]]) 
object AAndB { 
    implicit val implicitAAndBWrites = Json.writes[AAndB] 
} 

しかし、それはすべての場所で失敗します。 AとBの両方が、このように構成されている:Bので

sealed trait A extends SuperClass { 
    val a1: String = "identifier" 
} 

case class SubA(a2: ClassA2) extends A { 
    override val a1: String = "sub identifier" 
} 

object SubA { 
    val writes = Writes[SubA] { aa => 
     Json.obj(
      "a1" -> aa.a1 
      "a2" -> aa.a2 
     ) 
    } 
} 

リストとしてアクセスされ、期待される出力は、これらの線に沿って次のようになります

{ 
    "a":{ 
     "a1":"val1", 
     "a2":"val2" 
    }, 
    "b":[ 
     { 
     "b1":"val 3", 
     "b2":"val 4" 
     }, 
     { 
     "b1":"val 5", 
     "b2":"val 6" 
     }, 
     { 
     "b1":"val 7", 
     "b2":"val 8" 
     } 
    ] 
} 

あなたの助けが理解されます。

+0

あなたはAとBのjson構造とAとBを結合するサンプル最終的なjson構造を共有できますか? –

+0

'' future''を 'case class'プロパティとして持つことは疑問です – cchantep

答えて

0

あなたの質問のコメントにあるように、Futurecase class宣言の一部として使用することは非常に珍しいことです。ケースクラスは、不変のドメインオブジェクトをカプセル化する(つまり時間の経過とともに変化しない)

    Future
  • FutureFutureが正常に完了し
  • を失敗し、まだ完了していない
  • 、およびC:あなたはFuture[T]を伴うとして、あなたは潜在的に複数の結果を持っていますonインスタンス

あなたはJSONに変換する行為にこの一時的なものを絡ませたくありません。

case class AAndB(a: Option[A], b: Option[List[B]]) 
object AAndB { 
    implicit val implicitAAndBWrites = Json.writes[AAndB] 
} 

、代わりにそれぞれの内容にアクセスするために、あなたのControllerクラスでそれらのスカラ/プレイの非常に簡潔なハンドリングを使用します。このような理由から、あなたは取り外しFuture秒であなたのラッパークラスをモデル化する必要があります。そこでここでは、A-とB-クエリの両方を起動

def showCombinedJson(id:Int) = Action.async { 

    val fMaybeA = aService.findA(id) 
    val fMaybeBs = bService.findBs(id) 

    for { 
    maybeA <- fMaybeA 
    maybeBs <- fMaybeBs 
    } yield { 
    Ok(Json.toJson(AAndB(maybeA, maybeBs))) 
    } 
} 

class AService { 
    def findA(id:Int):Future[Option[A]] = ... 
} 

class BListService { 
    def findBs(id:Int):Option[Future[List[B]]] = ... 
} 

をここに私たちのコントローラのメソッドがどのように見えるかです:次のように例の下に、注入されたサービスクラスの存在を前提としで並行して(これを行うにはforの外側にこの並列性を達成する必要があります)。 Futureが正常に完了した場合、yieldブロックforのブロックがのみ実行されます。その時点で、その中の内容には安全にアクセスできます。 JSONに変換してOkの結果をPlayに返すことは、ラッパークラスのインスタンスを構築するという単純な問題です。実際の待機-のためのすべてとさせるプレイの契約 - yieldブロックの結果自体がFuture(この場合には、それはFuture[Result]だ)ので、我々はこれを処理するプレイのAction.asyncアクションビルダーを使用して内側にあるなること

注意 - 物事に - 起こる。

関連する問題