2017-06-19 35 views
0

由于22个字段的限制,我不得不将大型案例分成更小的类。我该如何将这个大班级的Writes变平?拼合写与玩JSON

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

case class B(x: Option[Int], y: Option[Int]) 

object B { 
    implicit val format: (Reads[B], Writes[B]) => Format[B] = Format[B] 
} 

case class C(z: Option[Int], w: Option[Int]) 

object C { 
    implicit val format: (Reads[C], Writes[C]) => Format[C] = Format[C] 
} 

case class A(b: B, c: C) 

object A { 
    implicit val reads: Reads[A] = 
    (Reads.of[B] and Reads.of[C]) (A.apply _) 

    implicit val writes: Writes[A] = ??? 
    /* 
    val a = A(B(1, 2), C(3, 4) 

    Json.toJson(a) should be 

    { 
    "x": 1 
    "y": 2 
    "z": 3 
    "w": 4 
    } 
    */ 
} 

回答

1

短篇小说,你可以这样做:

implicit val writes: Writes[A] = JsPath.write[B].and(JsPath.write[C]) (unlift(A.unapply _)) 

长的故事:为什么你能够使用and方法?

and适用于实现类型类FunctionalCanBuild的任何类。到目前为止我注意到的是,Writes没有这样的类型,但是有一个OWrites

使用JsPath.write[B]会产生OWrites值,因此and方法可用。另一方面,使用Writes.of[]产生Writes,并且OWrites.of[]产生Writes[]。最后,任何获得OWrites[]的方法都将允许您使用关键词和。

此外,仔细查看代码,Applicative typeclass的任何实例都可翻译为FunctionalCanBuild的实例。此类型类型适用于任何Reads,因此Readers.

+0

上的可用and方法什么是等同于此的读取? –