Reputation: 43
For example, we have some case class
case class Foo(a: Int, b: List[String])
And we want to deserialize instance of Foo
from json {"a": 1}
replacing missing b
array with Nil
We can create custom decoder for such behavior
implicit val fooDecoder: Decoder[Foo] = (c: HCursor) =>
for {
a <- c.downField("a").as[Int]
b <- c.downField("b").as[Option[List[String]]
} yield Foo(a, b.getOrElse(Nil))
But, unfortunately, the created this way decoder doesn't accumulate all decoding failures.
Is there any way to create decoder with failures accumulation or any way to replace standard list deserialization behavior in circe?
Upvotes: 4
Views: 2448
Reputation: 1017
You can also use .map(_.getOrElse(List.empty))
as well
implicit val fooDecoder: Decoder[Foo] = (c: HCursor) =>
for {
a <- c.downField("a").as[Int]
b <- c.downField("b").as[Option[List[String]].map(_.getOrElse(List.empty))
} yield Foo(a, b)
Upvotes: 1
Reputation: 48400
Try providing default value b: List[String] = Nil
using circe-generic-extras
like so
import io.circe.parser._
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.auto._
implicit val config: Configuration = Configuration.default.withDefaults
case class Foo(a: Int, b: List[String] = Nil)
val raw = """{"a": 1}"""
decode[Foo](raw) // res0: Either[io.circe.Error,Foo] = Right(Foo(1,List()))
where
libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % "0.12.0-M3",
"io.circe" %% "circe-parser" % "0.12.0-M3",
"io.circe" %% "circe-generic-extras" % "0.12.0-M3",
"io.circe" %% "circe-generic" % "0.12.0-M3"
)
Upvotes: 2