diff --git a/zio-json/shared/src/main/scala-2.x/zio/json/macros.scala b/zio-json/shared/src/main/scala-2.x/zio/json/macros.scala index 05c831cdc..3ca4469ef 100644 --- a/zio-json/shared/src/main/scala-2.x/zio/json/macros.scala +++ b/zio-json/shared/src/main/scala-2.x/zio/json/macros.scala @@ -297,10 +297,9 @@ object DeriveJsonDecoder { @tailrec private[this] def allowMissingValueDecoder(d: JsonDecoder[_]): Boolean = d match { - case _: OptionJsonDecoder[_] => true case _: CollectionJsonDecoder[_] => !explicitEmptyCollections case d: MappedJsonDecoder[_] => allowMissingValueDecoder(d.underlying) - case _ => false + case _ => true } override def unsafeDecodeMissing(trace: List[JsonError]): A = { diff --git a/zio-json/shared/src/main/scala-3/zio/json/macros.scala b/zio-json/shared/src/main/scala-3/zio/json/macros.scala index b9aac0d27..1e558faac 100644 --- a/zio-json/shared/src/main/scala-3/zio/json/macros.scala +++ b/zio-json/shared/src/main/scala-3/zio/json/macros.scala @@ -313,10 +313,9 @@ sealed class JsonDecoderDerivation(config: JsonCodecConfiguration) extends Deriv @tailrec private[this] def allowMissingValueDecoder(d: JsonDecoder[_]): Boolean = d match { - case _: OptionJsonDecoder[_] => true case _: CollectionJsonDecoder[_] => !explicitEmptyCollections case d: MappedJsonDecoder[_] => allowMissingValueDecoder(d.underlying) - case _ => false + case _ => true } override def unsafeDecodeMissing(trace: List[JsonError]): A = { diff --git a/zio-json/shared/src/test/scala/zio/json/DecoderSpec.scala b/zio-json/shared/src/test/scala/zio/json/DecoderSpec.scala index 7263b5252..014105de6 100644 --- a/zio-json/shared/src/test/scala/zio/json/DecoderSpec.scala +++ b/zio-json/shared/src/test/scala/zio/json/DecoderSpec.scala @@ -504,6 +504,21 @@ object DecoderSpec extends ZIOSpecDefault { assertTrue( json.fromJson[(Foo, Bar)] == Right((Foo(1), Bar("foo"))) ) + }, + test("option custom codec") { + val json = """{"keyStatus": "certified"}""" + final case class Foo(v: String) + final case class RudderSettings(keyStatus: String, policyMode: Option[Foo]) + implicit val encoderOptionPolicyMode: JsonEncoder[Option[Foo]] = JsonEncoder.string.contramap { + case None => "default" + case Some(f) => f.v + } + implicit val decoderOptionPolicyMode: JsonDecoder[Option[Foo]] = JsonDecoder[Option[String]].mapOrFail { + case None | Some("default") => Right(None) + case Some(s) => Right(Some(Foo(s))) + } + implicit lazy val codecRudderSettings: JsonCodec[RudderSettings] = DeriveJsonCodec.gen + assertTrue(json.fromJson[RudderSettings] == Right(RudderSettings("certified", None))) } ), suite("fromJsonAST")( @@ -843,5 +858,4 @@ object DecoderSpec extends ZIOSpecDefault { implicit val eventDecoder: JsonDecoder[Event] = DeriveJsonDecoder.gen[Event] implicit val eventEncoder: JsonEncoder[Event] = DeriveJsonEncoder.gen[Event] } - }