Denis Pakhomov
Denis Pakhomov

Reputation: 43

How to decode missing json array as empty List with circe

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

Answers (2)

Lukasz Lenart
Lukasz Lenart

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

Mario Galic
Mario Galic

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

Related Questions