2015-06-16 24 views
7

我有以下配置:提供隱含值在播放JSON庫單身

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

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

我想使用播放JSON格式,所以我想我必須有這樣的事情(我不想做它的同伴對象):

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

但編譯器抱怨說:

No implicit format for Tweet available.

另外它說我不能使用Edited.type,因爲它需要應用和不應用功能。我該怎麼辦?

EDIT1:

我能想到的是這樣的:

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

read部分有問題,編譯器會抱怨它需要JsonResult不Edited.type

回答

2

換做我應該做的定義像這樣的隱式對象:

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

也有可能與功能的API來做到這一點非常乾淨:

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] 

我覺得比實現readswrites方法手工,主要是因爲它強調了編碼和解碼之間的對稱性更清楚。不過,這是一個品味問題。

+0

'__'確實是兩個下劃線(需要記住很多符號:))?對稱性在哪裏? (儘量學會近期「功能性」,你推薦http://www.manning.com/bjarnason/或更好的東西?) – Omid

+0

是的,它確實是'__'。如果你不喜歡,你可以寫'JsPath'。我對運營商型的圖書館也持懷疑態度,但Play JSON只有一些運營商,我認爲它們非常合理。 –