我正在使用Play 2.1.0。我正在尝试创建一个接受POST请求的Action,并要求在请求体中需要一个布尔值。现在发生的事情是,即使我不提供参数,Action也会获得错误的值。测试代码:
// /post/boolean/single routes to this method
def postTestBooleanSingle = Action { implicit request =>
val form = Form("flag" -> boolean)
form.bindFromRequest.fold(
formWithErrors =>
BadRequest(formWithErrors.errors map (fe => fe.key + ": " + fe.message) mkString ", "),
flag => Ok(f"got $flag%b")
)
}
// /post/num/single routes to this method
def postTestNumSingle = Action { implicit request =>
val form = Form("num" -> number)
form.bindFromRequest.fold(
formWithErrors =>
BadRequest(formWithErrors.errors map (fe => fe.key + ": " + fe.message) mkString ", "),
num => Ok(f"got $num%d")
)
}
$ curl -XPOST -d "num=42" http://localhost:9000/post/num/single
got 42
$ curl -XPOST http://localhost:9000/post/num/single
num: error.required // didn't provide num so i get an error
$ curl -XPOST -d "flag=true" http://localhost:9000/post/boolean/single
got true
$ curl -XPOST http://localhost:9000/post/boolean/single
got false // ???
我如何需要布尔参数?
答案 0 :(得分:4)
我不知道为什么,但在没有任何参数的情况下,布尔类型的表格映射似乎默认为false。
以下是播放源中Format.scala的代码片段:
/**
* Default formatter for the `Boolean` type.
*/
implicit def booleanFormat: Formatter[Boolean] = new Formatter[Boolean] {
override val format = Some(("format.boolean", Nil))
def bind(key: String, data: Map[String, String]) = {
Right(data.get(key).getOrElse("false")).right.flatMap {
case "true" => Right(true)
case "false" => Right(false)
case _ => Left(Seq(FormError(key, "error.boolean", Nil)))
}
}
def unbind(key: String, value: Boolean) = Map(key -> value.toString)
}
这里的重要部分是data.get(key).getOrElse("false")
。在没有任何输入的情况下,它默认布尔值为false。您将需要创建一个自定义格式化程序,并使用它来定义布尔值的自定义绑定。
我会留给你把它们放在你的代码库中的好地方,但你的拼图应该是这样的:
// This is the custom formatter to support your custom mapping.
import play.api.data.format.Formatter
implicit def requiredBooleanFormatter: Formatter[Boolean] = new Formatter[Boolean] {
override val format = Some(("format.boolean", Nil))
def bind(key: String, data: Map[String, String]) = {
Right(data.get(key).getOrElse("")).right.flatMap {
case "true" => Right(true)
case "false" => Right(false)
case _ => Left(Seq(FormError(key, "error.boolean", Nil)))
}
}
def unbind(key: String, value: Boolean) = Map(key -> value.toString)
}
// This is your custom mapping to be used in the form
import play.api.data.Forms
val requiredBoolean: Mapping[Boolean] = Forms.of[Boolean](requiredBooleanFormatter)
请注意从.getOrElse("false")
到.getOrElse("")
的更改。代码几乎相同,但我们现在将空值推送到错误捕获器,而不是使它们取false
值。 (注意:为清楚起见,我在此示例中明确指定了requiredBooleanFormatter
,但由于requiredBooleanFormatter
是隐式的并且在范围内,因此您不必这样做。)
现在,您只需在表单中使用requiredBoolean
代替boolean
,即要求在请求中明确设置参数。