如何为具有超过 22 个字段的案例 class 编写隐式写入
How to write implicit Writes for case class having more than 22 fields
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
)
对于像这样的案例 class,我需要编写隐式 json 反/序列化程序。
我尝试拆分字段,并有一个 JSONFormat。但是我仍然需要隐式的 OWrited 来使用 Json.obj()。我也尝试使用 play-json-extensions。有什么想法吗?
这里实际上有 3 条途径供您探索:
- 自己明确地写出每个 class(是的,大量的样板文件。)
- 使用宏或 Shapeless。
- 使用已经做过 #2 的人的图书馆。
我喜欢别人为我工作。所以考虑到这一点,#3 似乎是我的首选解决方案......你知道什么?其他人就是这样做的:play-json-derived-codecs。由于它使用 Shapeless,因此它将能够处理任意大小的大小写 classses,而不仅仅是那些受 ProductN 限制的大小写(1-22,取决于您的 Scala 版本。)
不用play-json-extensions也可以实现。假设我们有一个超过 22 个字段的案例 class,如下所示:
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._
现在,播放不能serialize/deserialize 可选和日期字段。因此,我们需要为可选字段和日期字段编写隐式格式,如下所示:
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
}
}
对于 class 超过 22 个字段的情况,我们需要编写 写入 。
你可以看我的文章here..
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
)
对于像这样的案例 class,我需要编写隐式 json 反/序列化程序。 我尝试拆分字段,并有一个 JSONFormat。但是我仍然需要隐式的 OWrited 来使用 Json.obj()。我也尝试使用 play-json-extensions。有什么想法吗?
这里实际上有 3 条途径供您探索:
- 自己明确地写出每个 class(是的,大量的样板文件。)
- 使用宏或 Shapeless。
- 使用已经做过 #2 的人的图书馆。
我喜欢别人为我工作。所以考虑到这一点,#3 似乎是我的首选解决方案......你知道什么?其他人就是这样做的:play-json-derived-codecs。由于它使用 Shapeless,因此它将能够处理任意大小的大小写 classses,而不仅仅是那些受 ProductN 限制的大小写(1-22,取决于您的 Scala 版本。)
不用play-json-extensions也可以实现。假设我们有一个超过 22 个字段的案例 class,如下所示:
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._
现在,播放不能serialize/deserialize 可选和日期字段。因此,我们需要为可选字段和日期字段编写隐式格式,如下所示:
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
}
}
对于 class 超过 22 个字段的情况,我们需要编写 写入 。
你可以看我的文章here..