Reputation: 2045
Let's say I have
trait T
case class A(s: String) extends T
case class B(s: String, i: Int) extends T
I need to be able to serialize a List[T]
After declaring
implicit val aWrites = Json.writes[A]
implicit val bWrites = Json.writes[B]
I try to
val list = List(A("1"), B("2", 2))
Json.toJson(list)
but compiler says that
No Json serializer found for type T. Try to implement an implicit Writes or Format for this type.
my solutions is
implicit val tWrites = new Writes[T] {
def writes(t: T) = t match {
case a: A => Json.toJson(a)
case b: B => Json.toJson(b)
}
}
I don't like it, because it requires to change tWrite for each new class extending T.
Is there a more flexible implementation?
Upvotes: 2
Views: 245
Reputation: 11274
The Json.writes
macro requires an unapply
method, so you cannot use it with a trait. But even if you could, it would only serialize the parameters it knows from T. So your solution is the best you can do, although you probably (depending on use case) have to add a parameter that distinguishes between A and B when deserializing.
By the way, having to extend matches when you add a new type is a common problem (see expression problem). You should make your trait sealed
so the compiler will inform you when a pattern match statement misses a newly added type.
Upvotes: 0