Play json writes a subclass gives ambiguous values ​​of implicit values

I use a playback platform and have an abstract class:

 abstract class Base{...}

which has its own implicit JSON writer inside the companion object

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

I will subclass this abstract class:

case class SubClass{...}

which also has its own implicit JSON writer in its companion object

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

When I try to serialize a 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 a way to eliminate the ambiguity?

+2
source share
1 answer

You get a collision because it Writeshas a contravariant type parameter 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 .

+11

All Articles