2015-06-16 14 views
7

Ho seguente configurazione:Fornire valore implicito per single in gioco biblioteca JSON

sealed trait Status 
case object Edited extends Status 
case object NotEdited extends Status 

case class Tweet(content:String, status:Status) 

voglio usare Giocare formato JSON, quindi credo che devo avere qualcosa di simile (non voglio fare in oggetto associato):

trait JsonImpl{ 
    implicit val TweetFormat = Json.format[Tweet] 
    implicit val statusFormat = Json.format[Status] 
    implicit val StatusFormat = Json.format[Edited.type] 
    implicit val NotEditedFormat = Json.format[NotEdited.type] 
} 

ma compilatore si lamenta e dice:

No implicit format for Tweet available.

Inoltre dice che non posso usare Edited.type perché ha bisogno di applicare e funzioni non valide. Cosa dovrei fare?

Edit1:

posso pensare a qualcosa di simile:

implicit object StatusFormat extends Format[Status] { 
    def reads(json: JsValue) = 
     (json \ "type").get.as[String] match { 
     case "" => Edited 
     case _ => UnEdited 
     } 

    def writes(stat: Status) = JsObject(Seq(
     stat match { 
     case Edited => "type" -> JsString("Edited") 
     case NotEdited => "type" -> JsString("UnEdited") 
     } 
    )) 
    } 

ma la parte read ha problema, il compilatore si lamenta che ha bisogno JsonResult non Edited.type

risposta

2

Per farlo dovrei definire un oggetto implicito come questo:

implicit object StatusFormat extends Format[Status] { 
    def reads(json: JsValue) = 
     json match { 
     case JsString("Edited") => JsSuccess(Edited) 
     case JsString("NotEdited") => JsSuccess(NotEdited) 
     case _ => JsError("cannot parse it") 
     } 

    def writes(stat: Status) = JsString(stat.toString) 
} 
6

È anche possibile fare questo piuttosto pulito con l'API funzionale:

import play.api.data.validation.ValidationError 
import play.api.libs.functional.syntax._ 
import play.api.libs.json._ 

implicit val StatusFormat: Format[Status] = Format(
    (__ \ 'type).read[String].collect[Status](ValidationError("Unknown status")) { 
    case "UnEdited" => NotEdited 
    case "Edited" => Edited 
    }, 
    (__ \ 'type).write[String].contramap { 
    case Edited => "Edited" 
    case NotEdited => "UnEdited" 
    } 
) 

implicit val TweetFormat: Format[Tweet] = Json.format[Tweet] 

Ho trovato questo più chiara di attuazione reads e writes metodi a mano, soprattutto perché evidenzia la simmetria tra codifica e decodifica. È una questione di gusti, però.

+0

è '__' davvero due sottolineature (tanti simboli da ricordare :))? dov'è la simmetria? (prova ad imparare a guardare "funzionalmente" in questi giorni, mi consigliate http://www.manning.com/bjarnason/ o qualcosa di meglio?) – Omid

+0

Sì, è davvero "__". Puoi scrivere 'JsPath' se non ti piace. Sono anche scettico riguardo alle librerie pesanti per l'operatore, ma Play JSON ha solo un paio di operatori e penso che siano abbastanza ragionevoli. –