Last active
July 12, 2016 22:12
-
-
Save ostronom/fdbbf6e038b6fe4cd84a3caefc4f1ce7 to your computer and use it in GitHub Desktop.
uPickle derive.key-like behaviour for circe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats.data.Xor | |
import io.circe.parser._ | |
import io.circe._ | |
import io.circe.generic.encoding.DerivedObjectEncoder | |
import io.circe.syntax._ | |
import io.circe.generic.semiauto._ | |
sealed trait X | |
case class A(i: Int) extends X | |
case class B(i: Int) extends X | |
object Main extends App { | |
def genEncoder[T: DerivedObjectEncoder](tag: String) = new Encoder[T] { | |
val derived = deriveEncoder[T] | |
override def apply(u: T) = derived(u).mapObject(o => o.add("$type", tag.asJson)) | |
} | |
def genDecoder[T](discriminator: PartialFunction[String, Decoder[_ <: T]]) = new Decoder[T] { | |
override def apply(c: HCursor) = c.downField("$type").as[String] match { | |
case Xor.Right(tpe) if discriminator.isDefinedAt(tpe) => | |
discriminator(tpe)(c) | |
case _ => Xor.Left(DecodingFailure(s"Cannot deduce decoder", c.history)) | |
} | |
} | |
implicit val encoderA: Encoder[A] = genEncoder[A]("A") | |
implicit val encoderB: Encoder[B] = genEncoder[B]("B") | |
implicit val decoderA: Decoder[A] = deriveDecoder[A] | |
implicit val decoderB: Decoder[B] = deriveDecoder[B] | |
implicit val decoderC: Decoder[X] = genDecoder[X] { | |
case "A" => decoderA | |
case "B" => decoderB | |
} | |
val as = A(10).asJson.noSpaces | |
val bs = B(10).asJson.noSpaces | |
println(as, bs, parse(as).map(_.as[X]), parse(bs).map(_.as[X])) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment