2014-02-16 52 views
2

所以,我剛剛開始學習Scala。對不起,我提前無能。Play2.2.1框架中的Json Scala對象序列化

我試圖在stackoverflow上查找我的答案。我能找到幾個相關的主題,但我沒有發現我的問題。

我想發送一個基於Scala對象的json響應。我有一個動作,我做了以下內容:

def oneCredential = Action { 
    val cred = Credential("John", "Temp", "5437437") 
    Ok(Json.toJson(cred)) 
} 

我已經創造了它

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

case class Credential(name: String, account: String, password: String) 

object Credential{ 
    implicit val credentialWrites = (
    (__ \ "name").write[String] and 
    (__ \ "account").write[String] and 
    (__ \ "password").write[String] 
)(Credential) 
} 

當我試圖運行這個案例類和適當的隱寫操作[T] ,我有以下錯誤:「重載的方法值[適用]不能應用於(models.Credential.type)」。另外,我試過這個

implicit val credentialWrites = (
     (__ \ "name").write[String] and 
     (__ \ "account").write[String] and 
     (__ \ "password").write[String] 
)(Credential.apply _) 

失敗。錯誤:無法找到參數賦內含價值:play.api.libs.functional.Functor [play.api.libs.json.OWrites]

那麼這個:

implicit val credentialWrites = (
    (__ \ "name").writes[String] and 
    (__ \ "account").writes[String] and 
    (__ \ "password").writes[String] 
)(Credential) 

另一個失敗:「值寫入不是play.api.libs.json.JsPath的成員注意:隱式值credentialWrites在此處不適用,因爲它在應用程序點之後,並且缺少顯式結果類型「。對,我瞭解錯誤的第一部分,但不是第二部分。

最後,我發現了一個簡便的解決方案:

implicit val credentialWrites = Json.writes[Credential] 

有了這個我沒有錯誤,代碼終於奏效。我在blog上找到了解決方案。據說速記形式與上面「寫」的形式完全相同。但是這個「長」形式對我來說並不適用。

爲什麼速記版本工作,而長文件不工作?有人可以解釋這一點嗎?

謝謝!

PS版斯卡拉:2.10.2

回答

2

你給會爲Reads工作的定義,但Writes需要在最後一個別樣的說法。看看下面的例子:

case class Baz(foo: Int, bar: String) 

val r = (__ \ 'foo).read[Int] and (__ \ 'bar).read[String] 
val w = (__ \ 'foo).write[Int] and (__ \ 'bar).write[String] 

r可以應用到的功能(Int, String) => A得到Reads[A],這意味着我們可以按如下方式使用它(這些都是等效的):

val bazReader1 = r((foo: Int, bar: String) => Baz(foo, bar)) 
val bazReader2 = r(Baz.apply _) 
val bazReader3 = r(Baz) 

我們」什麼重新做的是將函數提升爲Reads的應用函數,以便我們可以將它應用於我們的Reads[Int]Reads[String](但是如果你不想這麼做,你不需要關心)。

w採取了不同類型的參數(同樣,你也不需要去關心,但這是因爲Writes有逆變仿函數,它沒有一個適用函子):

val bazWriter1 = w((b: Baz) => (b.foo, b.bar)) 

我們這裏,我們使用的情況下類的自動生成的提取,unapply,它返回一個Option[(Int, String)]

val bazWriter2 = w(unlift(Baz.unapply)) 

:能等效地寫爲下面。我們知道在這種情況下,它總是會返回一個Some,所以我們可以使用unlift(來自函數語法包,只是調用標準庫的Function.unlift)將Baz => Option[(Int, String)]轉換爲所需的Baz => (Int, String)

所以,只要改變你的最後一行)(unlift(Credential.unapply)),你很好去。

+0

非常感謝。 – Semuserable