2014-04-09 32 views
2

我想使用spray-json在Scala中創建案例類,但是在類中定義了一個asJson方法,但我似乎無法弄清楚如何。例如,我希望能夠做到這一點:如何使用spray-json將「asJson」方法作爲案例類的一部分?

case class Foo(bar: String) { 
    def toJson: JsValue = ... 
} 

這將是很容易建立一個隱含的JSON轉換器:

object JsonProtocols extends DefaultJsonProtocol { 
    implicit val fooFormat = jsonFormat1(Foo) 
} 

但據我所知,這不僅可以在班級之外完成。我很想找到一種方法來聲明JSON格式在類本身內轉換爲JSON。

回答

3

你能想象這樣做:

scala> import spray.json._ 
import spray.json._ 

scala> case class Foo(bar: String) { 
    def toJson:JsValue = JsObject("bar" -> JsString(bar)) 
} 
defined class Foo 

scala> Foo("bar").toJson 
res2: spray.json.JsValue = {"bar":"bar"} 

到目前爲止好,但不適合於噴霧的類型類的機制。例如,如果您嘗試將Foo轉換爲JsValue或從JsValue轉換(例如,使用路由entity(as[Foo]) { ... }),Spray的路由DSL會給您一個類型錯誤。也可能他們已經爲你準備的implicits,對於類型,如List和Set,與富貴工作:

scala> import DefaultJsonProtocol._ 
import DefaultJsonProtocol._ 

scala> List(Foo("bar")).toJson 
<console>:31: error: Cannot find JsonWriter or JsonFormat type class for List[Foo] 
       List(Foo("bar")).toJson 

因爲沒有JsonFormat類爲他們使用轉換符,就像一個JsonFormat1(Foo)會已經創造出來了。

那麼你可能會認爲把富同伴對象中的格式,因爲一個在範圍內一流的同伴對象是隱式的搜索路徑,像這樣:

object Foo extends DefaultJsonProtocol { 
    implicit val fooFormat = jsonFormat1(Foo) 
} 
case class Foo(bar: String) 

但是因爲我們沒有完成在這一點上定義富,編譯器爲我們提供了一個類型的錯誤:

[error] found : Foo.type 
[error] required: ? => ? 
[error] Note: implicit value fooFormat is not applicable here because it comes after the application point and it lacks an explicit result type 

加入RootJsonFormat[Foo]一個明確的結果類型不解決問題:

[error] found : Foo.type 
[error] required: ? => Foo 
[error] implicit val fooFormat:RootJsonFormat[Foo] = jsonFormat1(Foo) 

訣竅(!感謝knutwalker)是明確地傳遞Foo.apply

object Foo extends DefaultJsonProtocol { 
    implicit val fooFormat = jsonFormat1(Foo.apply) 
} 
case class Foo(bar: String) 
+0

同伴對象是隱式的搜索範圍的一部分。在伴侶中定義它就足夠了,它將在沒有明確導入的情況下被找到。 – knutwalker

+0

我似乎無法得到那個工作。我嘗試創建一個擴展了DefaultJsonProtocol的Foo對象,它包含'implicit val barFormat = jsonFormat1(Bar)',但是由於我還沒有完成對Bar的定義,因此編譯器不太滿意。如果你能做到這一點,你應該得到綠色支票;我會很高興地從你的答案中學習! – AmigoNico

+2

'Foo.apply'可以做到這一點,也就是'implicit val barFormat = jsonFormat1(Foo.apply)'。我放棄了它的要點:https://gist.github.com/knutwalker/10355424 – knutwalker

相關問題