2016-03-23 33 views
1

我想知道如何強制Play Scala框架表單映射器在數組屬性中保存空值。在Play框架表單映射數組中保留空值

例子。請求體(打印出片段的下面):

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) 
    } 
) 
} 

Form類與映射:

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 
) 
} 

我也試過的optionaldefault映射參數的某些組合,但結果仍是相同的。

使用0或任何其他數值而不是null不是這種情況。

有沒有人有任何想法如何實現這種形式的行爲?

在此先感謝您的時間和關注。

回答

2

它看起來像你發送JSON到表單端點。雖然這工作的簡單的JSON結構,你不能控制它是如何完成,因此得到像你看到的問題。

我會明確的關於是JSON端點,然後你可以定義自己的Reads[Option[Double]],工程你如何準確希望它

首先,定義在控制器級別的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要求 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) 
    } 
    ) 
} 
+0

謝謝您的明確答案。它解決了我的問題。 – serkas