I'm using the play framework, and have an abstract class:
abstract class Base{...}
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{...}
which also has its own implicit JSON writer within its companion object
object SubClass {
implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}
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?
You are getting a collision because
Writeshas a contravariant type parameterA:It means that
Writes[Base]is subclass ofWrites[SubClass]- you can useWrites[Base]whereWrites[SubClass]is required.The problem is here:
So
Writes[Base]should be able to serialize an instance ofSubClass. You could useADTin this case:With
sealedkeyword you'll get a warning in casematchis not exhaustive.