Skip to content

Instantly share code, notes, and snippets.

@melrief
Created June 12, 2016 09:29
Show Gist options
  • Save melrief/b924e9e0bbc95743d78ce83590d37ecb to your computer and use it in GitHub Desktop.
Save melrief/b924e9e0bbc95743d78ce83590d37ecb to your computer and use it in GitHub Desktop.
Problem with circe's Decoder[Option]
import cats.data.Xor
import io.circe._
sealed abstract class Predicate extends Product with Serializable
final case class Equal(int: Int) extends Predicate
final case class Bigger(int: Int) extends Predicate
case class Foo(opt: Option[Predicate])
object FooJsonCodec {
implicit val FooJsonDecoder = Decoder.instance(
cursor =>
cursor.downField("args").as[Option[Predicate]].map(Foo)
)
implicit val PredicateJsonDecoder: Decoder[Predicate] = Decoder.instance(
cursor => {
println(cursor.history)
cursor.focus.asArray.map(
_ match {
case List(operator, arg) => decodePredicate(operator, arg)
case _ => Xor.Left(DecodingFailure(s"""Cannot convert ${ cursor.focus } to operation""", cursor.history))
}
).getOrElse(
Xor.Left(DecodingFailure(s"Cannot decode predicate from ${ cursor.focus }", cursor.history))
)
}
)
private def decodePredicate(operator: Json, arg: Json): Decoder.Result[Predicate] = {
println(operator.hcursor.history + " " + arg.hcursor.history)
operator.as[String] match {
case Xor.Right(str) if str == "=" || str == ">" =>
arg.as[Int] match {
case Xor.Right(n) =>
str match {
case "=" => Xor.Right(Equal(n))
case ">" => Xor.Right(Bigger(n))
}
case Xor.Left(_) =>
Xor.Left(DecodingFailure(s"Argument for operator $str must be a number, got $arg", arg.hcursor.history))
}
case _ =>
Xor.Left(DecodingFailure(s"""Operator must be one of "=" or ">", got $operator""", operator.hcursor.history))
}
}
}
import FooJsonCodec._
object Main {
def main(args: Array[String]): Unit = {
val json = io.circe.jawn.parse("""
|{
| "args": ["=", "a"]
|}
""".stripMargin).getOrElse(sys.exit(-1))
println(Decoder[Foo].decodeJson(json))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment