本当にひどい JSON をデコードしようとしています。各オブジェクトの型情報は、 などのラベルが付いたフィールド内にエンコードされます。JSON のエンコード/デコードには Circe をtype
使用し"type": "event"
ています。ライブラリは型クラスを利用します。関連する型クラスはです。問題は、どの Decoder もタイプに対して不変であるということです。ここに具体的な例がありますdef apply(c: HCursor): Decoder.Result[A]
A
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" => // etc
// like a bunch of these
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 // a metric ton of additional fields
case class Departure(id: UUID, timestamp: DateTime, flightId: Int) extends Event // samsies as Arrival
デコードは正常に機能しますが、MotherEvent
常に返されます
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 を使用したいと考えています。Option[A]
考えられる解決策の 1 つは、60 または 70 フィールドを持つ「マザー」タイプを作成することですが、私はすでに自分が嫌いで、フィールドに基づいて埋められる70 フィールドのことだけを考えてプログラミングをやめたいと思っていtype
ます。
誰でもこれに対する良い解決策を考えることができますか?