Forms PlayScala表单映射

Forms PlayScala表单映射,forms,scala,playframework,Forms,Scala,Playframework,我正在尝试创建一个基于数据值的表单字段映射格式化程序,并分别映射到它的类 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" ->

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

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
验证来验证数据。但是我支持聪明代码的想法,所以在几次测试中,我回到了实现
格式化程序的表单

对于数据

{
 "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....
}