Skip to content

Instantly share code, notes, and snippets.

@marko-asplund
Last active September 23, 2018 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marko-asplund/d758dd4be12cd4cfd407513acdd6d95a to your computer and use it in GitHub Desktop.
Save marko-asplund/d758dd4be12cd4cfd407513acdd6d95a to your computer and use it in GitHub Desktop.
Subtype codecs with Circe
// ========== approach 1 ==========
sealed abstract class FooBase {
def subType: String = this.getClass.getSimpleName
}
case class Foo(a: Int, b: String) extends FooBase
case class Bar(c: Float, d: Int) extends FooBase
val fooName = getClassName(Foo.getClass)
val barName = getClassName(Bar.getClass)
implicit val fooDecoder: Decoder[Foo] = deriveDecoder
implicit val fooEncoder: Encoder[Foo] = deriveEncoder
implicit val barDecoder: Decoder[Bar] = deriveDecoder
implicit val barEncoder: Encoder[Bar] = deriveEncoder
implicit val decodeBaseFoo: Decoder[FooBase] = new Decoder[FooBase] {
final def apply(c: HCursor): Decoder.Result[FooBase] =
c.downField("subType").as[String] flatMap {
case `fooName` => c.as[Foo]
case `barName` => c.as[Bar]
}
}
implicit val encodeBaseFoo: Encoder[FooBase] = new Encoder[FooBase] {
final def apply(fb: FooBase): Json = fb match {
case f: Foo => f.asJson.mapObject(o => o.add("subType", Json.fromString(fooName)))
case b: Bar => b.asJson.mapObject(o => o.add("subType", Json.fromString(barName)))
}
}
// ========== approach 2 ==========
sealed abstract class FooBase
case class Foo(a: Int, b: String) extends FooBase
case class Bar(c: Float, d: Int) extends FooBase
implicit val fooDecoder: Decoder[Foo] = deriveDecoder
implicit val fooEncoder: Encoder[Foo] = deriveEncoder
implicit val barDecoder: Decoder[Bar] = deriveDecoder
implicit val barEncoder: Encoder[Bar] = deriveEncoder
implicit val fooBaseDecoder: Decoder[FooBase] = deriveDecoder
implicit val fooBaseEncoder: Encoder[FooBase] = deriveEncoder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment