Play JSON Encoding/Decoding Sequences of generic types

19 views
Skip to first unread message

Bruno Batarelo

unread,
Mar 17, 2018, 8:54:36 AM3/17/18
to Play Framework [deprecated]
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
Reply all
Reply to author
Forward
0 new messages