Argonaut CodecJson and decoding subtypes

566 Views Asked by At

In the Argonaut DecodeJson trait there is a method ||| for chaining together decoders, so that the first succeeding decoder is chosen. There is also a similar method in DecodeResult which has the same effect. It looks at first glance as though one of these would be what we want for decoding multiple subtypes of a common trait. However, how do we actually do this?

The first problem is that the argument to ||| has to be a DecodeJson decoding a supertype of the type that the callee is supposed to be decoding (and similarly for DecodeResult). I would expect that such a decoder would be able to decode all of the subtypes of the common supertype, so this seems like a recipe for infinite recursion!

We can get around this using the following ugly asInstanceOf hack while defining the CodecJson for the supertype:

c => c.as[A] ||| c.as[Foo](implicitly[DecodeJson[B]].asInstanceOf[DecodeResult[Foo]])

However, then there is still a problem when decoding more than two subtypes. Assume there are subtypes A, B and C of Foo. Now what? How do we add yet another alternative to this decoding expression? .asInstanceOf[DecodeResult[AnyRef]] is going to destroy the type-safety of the parsed result (as if we hadn't already discarded type-safety at this point!). And then we are quickly going to run out of options with 4, 5, or 6 alternatives.

EDIT: I will gladly accept as an answer any alternative approach to decoding more-than-2-wide subtype hierarchies using Argonaut.

0

There are 0 best solutions below