Circe:解码具有不同可能内容类型的容器类型

Circe: decoding a container type with different possible content types

我的目标是将 JSON 转换为以下模型:

case class Container(typeId: Int, timestamp: Long, content: Content)

sealed trait Content
case class ContentType1(...) extends Content
case class ContentType2(...) extends Content
case class ContentType3(...) extends Content

用 circe 解码它的好方法是什么?我想自动解码在这种情况下不起作用。

edit:json结构的文档将content字段描述为?mixed (object, integer, bool),所以也可以是简单的IntBoolean 而不是 case class 对象。但是现在可以忽略这两种类型(尽管有一个解决方案会很好)。

我会使用 semiauto(与 deriveDecoder),validate and or

case class Container[+C](typeId: Int, timestamp: Long, content: C)

sealed trait Content
@JsonCodec case class ContentType1(...) extends Content
@JsonCodec case class ContentType2(...) extends Content

object Content {
  import shapeless._
  import io.circe._
  import io.circe.generic.semiauto._

  def decodeContentWithGuard[T: Decoder](number: Int): Decoder[Content[T]] = {
    deriveDecoder[Content[T]].validate(_.downField("typeId") == Right(number), s"wrong type number, expected $number")
  }

  implicit val contentDecoder: Decoder[Container[Content]] = {
    decodeWithGuard[ContentType1](1) or
    decodeWithGuard[ContentType2](2)
  }
}

如果您不想要协变注释,则必须将内部 ContentTypeX 映射并向上转换为 Content

可能还有一个没有泛型的解决方案,但是你不能使用 semiauto。

可能无法编译,没有测试。