PlayScala 表单映射

PlayScala form mapping

我正在尝试创建一个基于数据值的表单字段映射格式化程序并分别映射到它的 class。

sealed trait Animal
case class MammalFormData(name: String, hairy: Boolean) extends Animal
case class BirdFormData(name: String, featherType: String) extends Animal

val studentForm = Form(mapping(
   "name" -> nonEmptyText,
   "height" -> of[Double],
   "pet" -> of[Animal](AnimalFormatter)
)(Student.apply)(Student.unapply))

然后我必须为下面的 Animal 数据对象创建格式化程序

object AnimalFormatter extends Formatter[Animal] {
  def bind(key: String, data: Map[String, String]) // How do i complete here

  def unbind....
}

如何使用以下 json 表单数据结构完成 AnimalFormatter 对象的 bind 部分?

{
 "name": "Jared Smith",
 "height": 5.2,
 "petType": "mammal",
 "pet": {
   "name": "Aaron Meow",
   "hairy": true
  }
 }

最初,我使用 Json 验证来验证数据。但我支持聪明代码的想法,所以我在几次测试中恢复了实现 Formatter 的形式。

对于数据

{
 "name": "Jared Smith",
 "height": 5.2,
 "petType": "mammal",
 "pet": {
   "name": "Aaron Meow",
   "hairy": true
  }
}

判断动物类型的鉴别器是petType。 这里的必要性是将pet的子数据提取到一个新的petDataMap.

object AnimalFormatter extends Formatter[Animal] {
  def bind(key: String, data: Map[String, String]): Either[Seq[FormError], Animal] = {
    // Most necessary
    val petDataMap = data
      .filter(_._1.startsWith(s"$key."))
      .map(kv => (kv._1.split('.').tail.mkString("."), kv._2))

    data.get("petType") match {
      case Some("mammal") =>
        mammalFormDataMapping.bind(petDataMap)

      case Some("bird") =>
        birdFormDataMapping.bind(petDataMap)

      case _=> Left(Seq(FormError("petType", "invalid.petType")))
    }
 }

  def unbind....
}