问题描述
我正在使用play框架,并且有一个抽象类:
I'm using the play framework, and have an abstract class:
abstract class Base{...}
在随播对象中有自己的隐式JSON编写器
which has its own implicit JSON writer within the companion object
object Base {
implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply))
}
我将这个抽象类子类化:
I subclass this abstract class:
case class SubClass{...}
在其伴随对象中也有自己的隐式JSON编写器
which also has its own implicit JSON writer within its companion object
object SubClass {
implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}
当我尝试使用Json.toJson(SubClass)序列化子类对象时,出现错误:
When I try to serialize the subclass object using Json.toJson(SubClass), I get an error:
[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)))
有什么方法可以消除歧义?
Is there any way to remove the ambiguity?
推荐答案
由于Writes
具有变量类型参数A
:
You are getting a collision because Writes
has a contravariant type parameter A
:
trait Writes[-A] extends AnyRef
这意味着Writes[Base]
是Writes[SubClass]
的子类-您可以在需要Writes[SubClass]
的地方使用Writes[Base]
.
It means that Writes[Base]
is subclass of Writes[SubClass]
- you can use Writes[Base]
where Writes[SubClass]
is required.
问题在这里:
val base: Base = new SubClass(...)
val jsBase = Json.toJson(base)
因此,Writes[Base]
应该能够序列化SubClass
的实例.在这种情况下,您可以使用ADT
:
So Writes[Base]
should be able to serialize an instance of SubClass
. You could use ADT
in this case:
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
不够详尽,则会收到警告.
With sealed
keyword you'll get a warning in case match
is not exhaustive.
这篇关于播放json写入子类会给出模棱两可的隐式值错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!