2013-01-08 6 views
11

ich mit dem neuen Spielen 2.1-RC1 Rahmen bin mit und ich habe eine Klasse, die eine Option [] Feld, so etwas wie dies hat:Wie optionale Felder in JSON Parsen im Spiel 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 wollen mit JSON-Strings umgehen können, die die optionalen "value" -Daten weglassen, z

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

(bearbeitet Frage) Ich kann das JSON-String umschreiben (eher plump), wie in dem Validierungsschritt gezeigt, aber gibt es ein einfacheres Muster I keine Versorgung für fehlende optionale Felder verwenden kann? Beachten Sie, dass dieses Neuschreiben nicht mit verschachtelten Strukturen oder irgendwo funktioniert, wo ich das fehlende Feld nicht einfach anhängen kann.

Antwort

6

Sie können dies einfach tun:

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

Das einzige Problem ist, dass der JSON nicht von der Anfrage kommt, sondern von einem Websocket. – NickStoughton

+0

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

+0

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

3

OK ... so die Antwort ist sehr einfach. Verwendung

fomatOpt() 

für optionale Felder. Der Testformatierer sieht nun so aus:

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

Was ist mit dem Fall, wenn Scala-Makros für das Injizieren von Lesen/Schreiben/Formatieren verwendet werden? Zum Beispiel können wir in Ihrem Fall nur schreiben 'implizite val testFormat = Json.format [Test]' Wie können Sie optionale JSON-Werte in diesem Fall verwalten? – visionary