2014-01-10 2 views
2

Я использую рамки игры, и есть абстрактный класс:игра JSON пишет подкласс дает неоднозначные неявные значения ошибки

abstract class Base{...} 

, который имеет свой собственный неявный JSON писатель внутри объекта компаньона

object Base { 
    implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply)) 
} 

I подкласс это абстрактный класс:

case class SubClass{...} 

, который также имеет свой собственный неявный JSON писатель ш 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] должен быть в состоянии сериализовать экземпляр SubClass. Вы можете использовать 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 не является исчерпывающим.

Смежные вопросы