Scala-Play表单:无法找到Enumeration子类型的Formatter类型类

时间:2017-03-17 12:58:51

标签: scala playframework enums

我正在使用Scala-Play 2.5.x并且需要定义一个需要映射的枚举类型的表单,即

object OptionType extends Enumeration {
  type Type = Value
  val Call = Value("Call")
  val Put = Value("Put")
  val Straddle = Value("Straddle")
}

case class MyParameters(impliedVolSpread: Double, optionType: OptionType.Type)

@Singleton
class MyForm @Inject()(implicit val messagesApi: MessagesApi) {
  val Instance = Form {
    mapping(
      "impliedVolSpread" -> of[Double],
      "optionType" -> of[OptionType.Type],
    )(MyParameters.apply)(MyParameters.unapply)
  }
}

但这会导致编译错误:

Cannot find Formatter type class for OptionType.Type. 
Perhaps you will need to import play.api.data.format.Formats._ 

在回顾其他类似的问题后,我认为这个用例已经解决,例如Enum Mapper PR 240

1 个答案:

答案 0 :(得分:2)

由于PR在Scala-Play 2.5.10中仍然无法使用,我偷了我需要的位并结束了这样的结束:

import play.api.data._
import play.api.data.format._
import play.api.data.Forms._

object EnumPlayUtils {
  //------------------------------------------------------------------------
  // public
  //------------------------------------------------------------------------
  /**
    * Constructs a simple mapping for a text field (mapped as `scala.Enumeration`)
    *
    * For example:
    * {{{
    * Form("gender" -> enum(Gender))
    * }}}
    *
    * @param enum the enumeration
    */
  def enum[E <: Enumeration](enum: E): Mapping[E#Value] = of(enumFormat(enum))

  /**
    * Default formatter for `scala.Enumeration`
    *
    */
  def enumFormat[E <: Enumeration](enum: E): Formatter[E#Value] = new Formatter[E#Value] {
    def bind(key: String, data: Map[String, String]) = {
      Formats.stringFormat.bind(key, data).right.flatMap { s =>
        scala.util.control.Exception.allCatch[E#Value]
          .either(enum.withName(s))
          .left.map(e => Seq(FormError(key, "error.enum", Nil)))
      }
    }

    def unbind(key: String, value: E#Value) = Map(key -> value.toString)
  }
}

并像这样使用:

@Singleton
class MyForm @Inject()(implicit val messagesApi: MessagesApi) {

    import EnumPlayUtils._   

    val Instance = Form {
        mapping(
             "impliedVolSpread" -> of[Double],
             "optionType" -> enum(OptionType),
        )(MyParameters.apply)(MyParameters.unapply)
    }
}