2
case class Foo(
  _1:Int,_2:Int,_3:Int,_4:Int,_5:Int,
  _21:Int,_22:Int,_23:Int,_24:Int,_25:Int,
  _31:Int,_32:Int,_33:Int,_34:Int,_35:Int,
  _41:Int,_42:Int,_43:Int,_44:Int,_45:Int,
  _51:Int,_52:Int,_53:Int,_54:Int,_55:Int
)

对于这样的案例类,我需要编写隐式 json de-/serializer。我尝试拆分字段,并有一个 JSONFormat。但是我仍然需要隐式 OWrited 来使用 Json.obj()。我也尝试使用 play-json-extensions。有任何想法吗?

4

2 回答 2

1

您可以在这里探索 3 条途径:

  1. 自己明确地写出每个类(是的,大量的样板。)
  2. 用 Macros 或Shapeless 来做
  3. 使用已经做过#2 的某人的图书馆。

我喜欢别人为我工作。所以考虑到这一点,#3 似乎是我的首选解决方案......你会知道什么?其他人就是这样做的:play-json-derived-codecs。由于它使用Shapeless,它将能够处理任意大小的案例类,而不仅仅是那些受 ProductN 限制的案例类(1-22,取决于您的 Scala 版本。)

于 2017-03-09T14:48:18.157 回答
1

我们可以在不使用play-json-extensions 的情况下实现。假设我们有一个超过 22 个字段的案例类,如下所示:

case class Foo(
  A: Int,
  B: Option[Int],
  C: String,
  D: Option[String],
  E: Seq[String],
  F: Date
  more fields..
)

现在我们将字段拆分并分组为一些组并编写格式。

val fooFormat1: OFormat[(Int, Option[Int], String)] =
    ((__ \ "A").format[Long]
      ~ (__ \ "B").format[Option[Long]]
      ~ (__ \ "C").format[Option[Long]]).tupled


val fooFormat2: OFormat[(Option[String], Seq[String], Date)] =
    ((__ \ "D").format[Long]
      ~ (__ \ "E").format[Option[Long]]
      ~ (__ \ "F").format[Option[Long]]).tupled 

最后将所有格式合并为一种格式。

 implicit val fooFormat: Format[Foo] = (fooFormat1 ~ fooFormat2)({
     case ((a, b, c), (d, e, f)) =>
      new Foo(a, b, c, d, e, f)
   }, (foo: Foo) => ((
    foo.A,
    foo.B,
    foo.C
  ), (
      foo.D,
      foo.E,
      foo.F
    )))

我们需要像下面这样导入函数语法:

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

现在,play 不能序列化/反序列化可选和日期字段。因此,我们需要为可选字段和日期字段编写隐式格式,如下所示:

implicit object DateFormat extends Format[java.util.Date] {
    val format = new java.text.SimpleDateFormat("yyyy-MM-dd")
    def reads(json: JsValue): JsResult[java.util.Date] = JsSuccess(format.parse(json.as[String]))
    def writes(date: java.util.Date): JsString = JsString(format.format(date))
  }

implicit def optionFormat[T: Format]: Format[Option[T]] = new Format[Option[T]] {
    override def reads(json: JsValue): JsResult[Option[T]] = json.validateOpt[T]

    override def writes(o: Option[T]): JsValue = o match {
      case Some(t) => implicitly[Writes[T]].writes(t)
      case None    => JsNull
    }
  }

这就是我们为超过22 个字段的案例类编写Writes所需的全部内容。

你可以在这里阅读我的文章..

于 2017-09-08T06:14:21.153 回答