2013-01-08 4 views
11

sto usando il nuovo quadro Gioco 2.1-RC1 e ho una classe che ha un campo di opzione [], qualcosa di simile:Come gestire i campi facoltativi in ​​JSON parsing in gioco 2.1

import play.api.libs.json._ 
import play.api.libs.json.util._ 
import play.api.libs.json.Reads._ 
import play.api.libs.json.Writes._ 
import play.api.libs.json.Format._ 
import play.api.libs.functional.syntax._ 

case class Test(name: String, value: Option[String]) 

object Test { 
    implicit val testFormat = (
    (__ \ "name").format[String] and 
    (__ \ "value").format[Option[String]] 
)(Test.apply, unlift(Test.unapply)) 
    def fromJson(js: String): Test = { 
    Json.fromJson[Test](Json.parse(js)).fold(
     valid = { t => t}, 
     invalid = { e => { 
      val missingField = (e(0)._1).toString.substring(1) 
      val badJs = js.trim 
      val newJs = badJs.substring(0, badJs.length()-1)+",\""+missingField+"\":null}" 
      fromJson(newJs) 
     }} 
    ) 
    } 
} 

I vuoi essere in grado di gestire stringhe JSON che omettono i dati "valore" opzionali, ad es

val y = """{"name":"someone"}""" 

(domanda a cura) posso riscrivere la stringa JSON (piuttosto maldestramente) come mostrato nella fase di convalida, ma C'è un modello più semplice che posso usare per fornire Nessuno mancanti Campi facoltativi? Nota che questa riscrittura non funziona con le strutture nidificate, o dovunque non posso semplicemente aggiungere il campo mancante.

risposta

6

Si può semplicemente fare questo:

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

case class Test(name: String, value: Option[String]) 

implicit val testFormat = Json.format[Test] 

def hoge = Action(Json.parse.json) { request => 
    Json.fromJson[Test](request.body) 
    ... 
} 
+0

L'unico problema è che JSON non proviene dalla richiesta ma da una websocket. – NickStoughton

+0

@NickStoughton 'Iteratee.foreach [JsValue] (event => Json.fromJson [Test] (evento))' – sndyuk

+0

@NickStoughton JFYI https://github.com/playframework/Play20/blob/master/samples/scala/websocket -chat/app/models/ChatRoom.scala – sndyuk

3

OK ... quindi la risposta è molto semplice. Utilizzare

fomatOpt() 

per campi facoltativi. Il formattatore di test ora appare così:

import play.api.libs.json._ 
import play.api.libs.json.util._ 
import play.api.libs.json.Reads._ 
import play.api.libs.json.Writes._ 
import play.api.libs.json.Format._ 
import play.api.libs.functional.syntax._ 

case class Test(name: String, value: Option[String]) 

object Test { 
    implicit val testFormat = (
    (__ \ "name").format[String] and 
    (__ \ "value").formatOpt[String] 
)(Test.apply, unlift(Test.unapply)) 

    def fromJson(js: String): Test = { 
    Json.fromJson[Test](Json.parse(js)).fold(
     valid = { t => t}, 
     invalid = { e => { 
     println("BAD JSON!") 
     null 
     }} 
    ) 
    } 
} 
+2

Che dire del caso quando si usano macro di scala per l'iniezione di letture/scritture/formato? Per esempio nel tuo caso possiamo scrivere solo 'implicit val testFormat = Json.format [Test]' Come puoi gestire i valori JSON facoltativi in ​​quel caso? – visionary