我有一个包含10个以上字段的大案例类,它代表来自用户的JSON有效负载。大多数字段都是可选的,所以我在这种情况下使用Option
(Option[String]
用于字符串字段。这是很好的方法,直到我需要一个可选的序列。我认为编写选项[ Seq [String]]很奇怪,因为空序列足以显示没有数据(出于任何原因)。
不过我可以手动处理它:
implicit val reads = new Reads[MyCaseClass] {
def reads(js: JsValue): JsResult[MyCaseClass] = {
JsSuccess(MyCaseClass(
(js \ "unit_code").as[String],
// other fields omited
(js \ "positions").asOpt[Seq[String]] match {
case Some(seq: Seq[String]) => seq
case None => Seq.empty[String]
}
))
}
}
但我不想手动编写所有这些东西。可能会有错误,我需要单独测试,而且,肯定会花费更多时间,而不是写implicit val f = Json.format[MyCaseClass]
。
是否有任何选项可以单独处理一个字段,其他字段处理默认宏?
答案 0 :(得分:1)
感谢用户'cchantep'指向Json transformers。 这就是我解决问题的方法:
案例类:
case class MyCaseClass(unit_code: String, positions: Seq[String] = Seq.empty)
伴随对象
object MyCaseClass {
private val readsTransformer: Reads[JsObject] = __.json.update(
__.read[JsObject]
.map{ o =>
if (o.keys.exists(p => p.equals("positions"))) {
o
} else {
o ++ Json.obj("positions" -> JsArray())
}
}
)
implicit val readsImplicit: Reads[MyCaseClass] = readsTransformer.andThen(Json.reads[MyCaseClass])
implicit val writesImplicit: OWrites[MyCaseClass] = Json.writes[MyCaseClass]
}
这看起来有点麻烦,但是可以编写为精确字段创建变换器的公共函数,因此在每个伴随对象中它不会那么冗长。