2014-01-10 54 views
2

我使用的是發揮框架,並有一個抽象類:發揮JSON寫入子給出了模棱兩可的隱含值​​誤差

abstract class Base{...} 

其中有同伴對象

object Base { 
    implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply)) 
} 
中有自己的隱含JSON作家

我從這個抽象類繼承而來:

case class SubClass{...} 

其中也有它自己的隱式JSON寫入器w ithin它的同伴對象

object SubClass { 
    implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply)) 
} 

當我試圖序列使用Json.toJson(子類)的子類對象,我得到一個錯誤:

[error] both value subClassWrites in object SubClass of type => play.api.libs.json. 
Writes[models.SubClass] 
[error] and value baseWrites in object Base of type =>   
play.api.libs.json.Writes[models.Base] 
[error] match expected type play.api.libs.json.Writes[models.SubClass] 
[error] Ok(Json.toJson(SubClass.find(id))) 

有什麼辦法消除不確定性?

回答

11

你得到一個衝突,因爲Writes有逆變類型參數A

trait Writes[-A] extends AnyRef 

這意味着Writes[Base]Writes[SubClass]子類 - 你可以使用Writes[Base]在需要Writes[SubClass]

的問題是在這裏:

val base: Base = new SubClass(...) 
val jsBase = Json.toJson(base) 

所以Writes[Base]應該能夠序列化的​​一個實例。你可以在這種情況下使用ADT

sealed trait Base 
object Base { 
    implicit val baseWrites: Writes[Base] = 
    new Writes[Base]{ 
     def writes(o: Base): JsValue = o match { 
     case s: SubClass => SubClass.writes.writes(s) 
     case s: SubClass2 => SubClass2.writes.writes(s) 
     } 
    } 
} 

case class SubClass(...) extends Base 
object SubClass { 
    val writes: Writes[SubClass] = (...)(unlift(SubClass.unapply)) 
} 

case class SubClass2(...) extends Base 
object SubClass2 { 
    val writes: Writes[SubClass2] = (...)(unlift(SubClass2.unapply)) 
} 

隨着sealed關鍵字,你會得到一個警告的情況下,match並不詳盡。