Hi all,
I wanted to discuss a bit weird scenario when decoding sequence of polymorphic json data. For brevity and clarity, let's assume we have:
1 - trait BaseType
and
2 a case class of SubType extending BaseType.
Our Json envelope class could look something like this case class Envelope(..., baseType: Seq[BaseType])
This scenario works as expected. We create formats in a proper order and all works well:
implicit val baseTypeFormat: Format[BaseType] = new Format[BaseType] {
// manual implementation of reads/writes for all possible subtypes...
}
implicit val envelopeFormat: Format[Envelope] = Json.format
Suppose we want to now change Envelope to contain Seq[SubType] instead of BaseType. One would think that adding one more format in front of everything will do the trick:
implicit val subTypeFormat: Format[SubType] = Json.format
but unfortunately it doesn't work and compiler complains about format Format[Seq[SubType]] not being present in implicit scope. That is technically true and implementing that particular format works, although it's rather cumbersome. On the other hand, I don't understand why it's not working for members of subclasses when it's working correctly for other scenarios. For instance, this is quite standard stuff and is working as expected:
case class Child(...)
case class Parent(..., children: Seq[Child])
implicit val childFormat: Format[Child] = Json.format
implicit val parentFormat: Format[Parent] = Json.format
---
Problem with former approach is that in situations where I need Envelope(subtypes: Seq[SubType]), in order to have "clean" deserialising code I must have Envelope(baseTypes: Seq[BaseType]) and then later cast those members of collection into SubType what I expected to see earlier and that can be error prone.
Thanks,
Bruno