2016-03-23 11 views
1

Ich versuche eine Idee zu bekommen, wie kann ich zwingen, Scala Framework Form Mapper Null Werte in Array-Eigenschaft zu speichern.Nullwerte im Array von Play-Framework-Form-Mapping erhalten

Beispiel. Anfrage Körper (druckt unten aus Snippet):

AnyContentAsJson({ 
"entities":["ENI","GDF Suez","Procter & Gamble"], 
"entityValues":[null,"42",null] 
}) 

resultierenden Wert von entityValues Eigenschaft nach der Bindung:

List(Some(42.0)) 

Aber ich will sehen:

List(None, Some(42.0), None) 

-Code-Snippet-Controller:

def actionX = Action {implicit request => 
    println(request.body) 
    TaskForm.form.bindFromRequest.fold(
    formWithErrors => { 
     BadRequest("error") 
    }, 
    taskData => { 
     println(taskData.entityValues) 
    } 
) 
} 

Form-Klasse mit Mapping:

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

Ich habe auch versucht, einige Kombinationen von optional und default Mapping-Parameter, sondern ein Ergebnis ist immer noch das gleiche.

Mit 0 oder einem anderen numerischen Wert anstelle von null ist kein Fall.

Hat jemand irgendwelche Ideen, wie man solches Formularverhalten implementiert?

Vielen Dank im Voraus für Ihre Zeit und Aufmerksamkeit.

Antwort

2

Offenbar senden Sie JSON an einen Formularendpunkt. Während diese für einfache JSON-Strukturen arbeiten, haben Sie keine Kontrolle darüber, wie es gemacht wird und damit Probleme wie die, die Sie sehen.

Ich würde explizit über einen JSON-Endpunkt zu sein, und dann können Sie Ihre eigenen Reads[Option[Double]] definieren, die genau funktioniert, wie Sie es haben wollen:

Zunächst definieren die implicits auf Controller-Ebene; Hier können wir die null -Handhabung steuern; es endet als ziemlich einfach:

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] 

Wenn das getan ist, wir ändern Ihre Action- JSON erfordern (mit parse.json). Die Funktion selbst bleibt bemerkenswert ähnlich der ursprünglichen Form verbindlich 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

Vielen Dank für eine klare Antwort. Es löst mein Problem. – serkas