Scala / Play:修改单个字段的Json.format宏行为

时间:2018-01-05 14:18:11

标签: json scala playframework

我有一个包含10个以上字段的大案例类,它代表来自用户的JSON有效负载。大多数字段都是可选的,所以我在这种情况下使用OptionOption[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]

是否有任何选项可以单独处理一个字段,其他字段处理默认宏?

1 个答案:

答案 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]
}

这看起来有点麻烦,但是可以编写为精确字段创建变换器的公共函数,因此在每个伴随对象中它不会那么冗长。