我正在尝试解码一些真正可怕的 JSON。每个对象的类型信息都在标记为type
ie"type": "event"
等的字段中编码。我使用Circe进行 JSON 编码/解码。该库使用类型类,其中相关的类型类是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 而不是母事件。一种可能的解决方案是创建一个具有 60 或 70 个字段的“母亲”类型,但我已经讨厌自己并且想退出编程,只考虑Option[A]
基于字段填充的70 个字段type
。
谁能想到一个好的解决方案?