0

由于 22 个字段的限制,我不得不将一个大型案例类拆分为较小的类。我怎样才能扁平化Writes这个大类?

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
  }
   */
}
4

1 回答 1

1

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

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

长话短说:你为什么可以使用and方法?

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

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

此外,进一步研究代码,Applicativetypeclass 的任何实例都可以转换为FunctionalCanBuild. 这个类型类是为任何Reads因此可用的and方法实现的Readers.

于 2017-06-19T12:20:57.437 回答