Play JSON写子类导致模糊的隐式值错误

3

我正在使用Play框架,有一个抽象类:

 abstract class Base{...}

伴生对象中有内置的JSON编写程序

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

我继承了这个抽象类:

case class SubClass{...}

该对象还具有其自己的隐式 JSON writer,位于其伴生对象中

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

当我尝试使用Json.toJson(SubClass)序列化子类对象时,出现错误:
[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)))

有没有办法消除歧义?
1个回答

14

您之所以会遇到碰撞,是因为Writes具有逆变类型参数A

trait Writes[-A] extends AnyRef

这意味着Writes [Base]Writes [SubClass]的子类 - 您可以在需要Writes [SubClass]的地方使用Writes [Base]

问题就在这里:

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

所以Writes[Base]应该能够序列化SubClass的实例。在这种情况下,您可以使用ADT

因此,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不是穷尽的,你将会收到一个警告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接