Created
June 12, 2016 09:29
-
-
Save melrief/b924e9e0bbc95743d78ce83590d37ecb to your computer and use it in GitHub Desktop.
Problem with circe's Decoder[Option]
This file contains hidden or 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._ | |
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