Skip to content

Instantly share code, notes, and snippets.

@fserra-mdsol
Created September 13, 2023 17:44
Show Gist options
  • Save fserra-mdsol/db60d1ca66c2b67344f2e54d762dd4d4 to your computer and use it in GitHub Desktop.
Save fserra-mdsol/db60d1ca66c2b67344f2e54d762dd4d4 to your computer and use it in GitHub Desktop.
// This gist showcase a Circe JSON Decoder for which a null value in a field gets decoded into some
// arbitrary type, instead of being treated as if it was not present in the request and decoded into None.
// This behaviour is semantically unsound, but so are sometimes the business requirements for application development
//> using scala "2.13.10"
//> using lib "io.circe::circe-core::0.14.6"
//> using lib "io.circe::circe-generic::0.14.6"
//> using lib "io.circe::circe-parser::0.14.6"
import io.circe._, io.circe.parser._
import io.circe.generic.semiauto._
import cats.syntax.all._
object CirceDecoder extends App {
case class Foo(bar: Option[String], baz: Int)
object Foo {
implicit val decoderFoo: Decoder[Foo] = Decoder.instance { c =>
for {
bar <- c.downField("bar").focus match {
case Some(json) if json.isNull => "I was null!".some.asRight
case Some(json) => json.asString.asRight
case _ => none[String].asRight
}
baz <- c.downField("baz").as[Int]
} yield Foo(bar, baz)
}
}
val json1 =
"""
{
"bar" : null,
"baz" : 1
}
"""
val json2 =
"""
{
"bar" : "I was NOT null!",
"baz" : 1
}
"""
val json3 =
"""
{
"baz" : 1
}
"""
def jsonEqualsTo(json: String, foo: Foo): Boolean = {
(for {
parseResult <- parse(json)
jsonResult <- parseResult.as[Foo]
} yield jsonResult).contains(foo)
}
assert(jsonEqualsTo(json1, Foo(Some("I was null!"),1)))
assert(jsonEqualsTo(json2, Foo(Some("I was NOT null!"),1)))
assert(jsonEqualsTo(json3, Foo(none[String],1)))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment