我试图了解如何强制Play Scala框架表单映射器在数组属性中保存空值。
实施例。请求正文(打印出下面的代码段):
AnyContentAsJson({
"entities":["ENI","GDF Suez","Procter & Gamble"],
"entityValues":[null,"42",null]
})
绑定后entityValues
属性的结果值:
List(Some(42.0))
但我希望看到:
List(None, Some(42.0), None)
控制器的代码片段:
def actionX = Action {implicit request =>
println(request.body)
TaskForm.form.bindFromRequest.fold(
formWithErrors => {
BadRequest("error")
},
taskData => {
println(taskData.entityValues)
}
)
}
带有映射的表单类:
case class TaskForm(entities: List[String],
entityValues: List[Option[Double]]) { }
object TaskForm {
val map = mapping(
"entities" -> list(text),
"entityValues" -> list(optional(of(doubleFormat)))
)(TaskForm.apply)(TaskForm.unapply)
val form = Form(
map
)
}
我还尝试了optional
和default
映射参数的某些组合,但结果仍然相同。
使用0
或任何其他数字值代替null
并非如此。
有没有人有任何想法如何实现这种表单行为?
提前感谢您的时间和关注。
答案 0 :(得分:3)
您似乎正在将JSON发送到表单端点。虽然这个将适用于简单的JSON结构,但是你无法控制它是如何完成的,因此会遇到像你所看到的那样的问题。
我明确表示要成为JSON端点,然后您可以定义自己的Reads[Option[Double]]
正是您想要的:
首先,在Controller级别定义implicits;在这里我们可以控制null
- 处理;它最终很容易:
implicit val optionalDoubleReads = new Reads[Option[Double]] {
def reads(json: JsValue) = json match {
case JsNumber(n) => JsSuccess(Some(n.toDouble))
case JsString(n) => JsSuccess(Some(n.toDouble))
case JsNull => JsSuccess(None) // The important one
case _ => JsError("error.expected.jsnumber")
}
}
implicit val taskReads = Json.reads[TaskForm]
完成上述操作后,我们会将您的Action
修改为 require JSON(使用parse.json
)。函数本身与原始的表单绑定fold
:
def actionX = Action(parse.json) { implicit request =>
println(request.body)
request.body.validate[TaskForm].fold(
jsonErrors => {
BadRequest(s"Error: $jsonErrors")
},
taskData => {
println(taskData.entityValues)
Ok(taskData.entityValues.toString)
}
)
}