2013-07-15 71 views
7

我想產生JSON爲包括基類和派生類的List。下面的代碼只爲Animal類生成JSON(我沒有得到Dog類成員的品種領域)。一些幫助將不勝感激。斯卡拉播放框架2.1派生類

import play.api.libs.json._ 

class Animal (val name:String) { 
} 

object Animal { 
    implicit object animalWrite extends Writes[Animal] { 
    def writes(ts: Animal) = JsObject(Seq("name" -> JsString(ts.name))) 
    } 
} 

case class Dog (override val name:String, val breed: String) 
    extends Animal(name) { 
} 

object Dog { 
    implicit val format = Json.format[Dog] 
} 

case class Cat (override val name:String, val hairLength: Int) 
    extends Animal(name) { 
} 

object Cat { 
    implicit val format = Json.format[Cat] 
} 

object helloWorld extends App { 
// The list below outputs:  [{"name":"Ruff","breed":"labrador"}] 
// val l = List[Dog](Dog("Ruff", "labrador")) 

// The list below outputs:  [{"name":"Ruff"},{"name":"Fluffy"}] 
// I expect to see: [{"name":"Ruff","breed":"labrador"},{"name":"Fluffy","hairLength":3}] 
    val l = List[Animal](Dog("Ruff", "labrador"), Cat("Fluffy", 3)) 
    println(Json.toJson(l)) 
} 

Scala和Play新手在這裏,請原諒不適當使用的術語。

回答

5

JSON API使用廣泛使用隱含參數,這是斯卡拉的一個功能,您可以提供一個「隱」的參數列表,如果你不指定這些參數,編譯器將嘗試找到在當前範圍內是一個對象標記爲隱含並與該簽名匹配。

所以,如果你比如這樣寫:

implicit val s = "my implicit string" 

def magicPrint(implicit message: String) { println(message) } 

// and then call it 
magicPrint 

,編譯器將選擇S爲參數消息,因爲它是在範圍和具有正確的類型(String),所以隱式解析,最後一行之後的代碼實際上看起來會像這樣

magicPrint(s) 

格式化/寫入器是由編譯器選擇,在編譯的時候,有一個隱含的參數。如果你看一下方法,toJson[A](item: A)(implicit writes: Writes[A])的簽名,它需要一個隱含Writes[A]而你的情況是因爲Writes[List[Animal]]List[Animal]您的列表l的類型。遊戲包含了默認有一個作家是負責收集(DefaultWrites.traversableWrites)這又需要一個隱含Writes[A]的 - 你的情況Writes[Animal],所以編譯器將選擇並通過您animalWrites。

那你的列表中包含不同種類的動物是什麼,發生在運行時,編譯器無法知道從可用類型的信息您Json.toJson(l)

這樣的方式,因爲你看你能不能達到你想要什麼在路上,你想,但你可以通過讓動物筆者瞭解的亞型,例如做它在幾乎相同的方式:

implicit object animalWrite extends Writes[Animal] { 
    def writes(ts: Animal) = ts match { 
    // this will get an implicit Writes[Dog] since d is a Dog 
    case d: Dog => Json.toJson(d) 
    // this will get an implicit Writes[Cat] since c is a Cat 
    case c: Cat => Json.toJson(c) 
    case x => throw new RuntimeException(s"Unknown animal $x") 
    } 
} 

希望這有助於!

+0

謝謝johanandren。這很有幫助,我認爲這個問題與暗示有關,但我不知道如何。我所做的解決方法是在Dog和Cat中實現一個調用'Json.toJson(this)'的序列化方法,並用'l.map(_。serialize).mkString(「[」,「 「,」]「)'。你的更好,因爲你不必像我一樣手動連接Json。謝謝。 – ariscris

+0

Is'nt最好添加在動物女巫的函數的toJSON可以像 ''' 情況下類狗(重寫VAL名:字符串,VAL品種:字符串)來實現 延伸動物(名稱){ DEF的toJSON = Json.toJson(this) } ''' – crak

+0

通常這樣做是可以避免的,因爲它會混合並緊密地將你的領域模型與一種形式的序列化的實現細節緊密耦合,而播放json的類型類通常使用很好的decouples這個。 – johanandren

相關問題