I am trying to decode some really terrible JSON. Type information for each object is encoded in a field with a label type, i.e., "type": "event"etc. I use Circe for JSON encoding / decoding. The library uses type classes, where the corresponding class type def apply(c: HCursor): Decoder.Result[A]. The problem is that any decoder is invariant to the type A. Here is a concrete example
sealed trait MotherEvent {
val id: UUID
val timestamp: DateTime
}
implicit val decodeJson: Decoder[MotherEvent] = new Decoder[MotherEvent] {
def apply(c: HCursor) = {
c.downField("type").focus match {
case Some(x) => x.asString match {
case Some(string) if string == "flight" => FlightEvent.decodeJson(c)
case Some(string) if string == "hotel" =>
case None => Xor.Left(DecodingFailure("type is not a string", c.history))
}
case None => Xor.Left(DecodingFailure("not type found", c.history))
}
}
sealed trait FlightEvents(id: UUID, timestamp: DateTime, flightId: Int)
case class Arrival(id: UUID, timestamp: DateTime, flightId: Int) extends Event
case class Departure(id: UUID, timestamp: DateTime, flightId: Int) extends Event
Decoding works fine, but MotherEventalways returns
val jsonString = // from wherevs, where the json string is flightevent
val x = decode[MotherEvent](jsonString)
println(x) // prints (cats.data.Xor[io.circe.Error, MotherEvent] = Right(FlightEvent)
println(x.flightId) // ERROR- flightId is not a member of MotherEvent
, FlightEvent . - "" , 60 70 , , 70 Option[A] , type.
- ?