-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to emit null
instead of nothing when decoding Option[A]
?
#638
Comments
@beneyal , here's what is a snippet I managed to make it work. hope that helps! import zio.json._
import zio.json.ast._
import zio.json.internal.Write
case class OptionAsJsonNull[+A](value: Option[A]) extends AnyVal
object OptionAsJsonNull {
// optional implicit conversion methods to make it easier to work with
implicit def toOption[A](value: OptionAsJsonNull[A]): Option[A] = value.value
implicit def fromOption[A](value: Option[A]): OptionAsJsonNull[A] = OptionAsJsonNull(value)
private def decoder[A](implicit A: JsonDecoder[A]): JsonDecoder[OptionAsJsonNull[A]] =
JsonDecoder[Option[A]].map(OptionAsJsonNull(_))
// modified on top of JsonEncoder.option
private def encoder[A](implicit A: JsonEncoder[A]): JsonEncoder[OptionAsJsonNull[A]] = new JsonEncoder[Option[A]] {
def unsafeEncode(oa: Option[A], indent: Option[Int], out: Write): Unit = oa match {
case None => out.write("null")
case Some(a) => A.unsafeEncode(a, indent, out)
}
override def isNothing(oa: Option[A]): Boolean =
oa match {
case None => false
case Some(a) => A.isNothing(a)
}
override final def toJsonAST(oa: Option[A]): Either[String, Json] =
oa match {
case None => Right(Json.Null)
case Some(a) => A.toJsonAST(a)
}
}.contramap(_.value)
implicit def codec[A](implicit A: JsonCodec[A]): JsonCodec[OptionAsJsonNull[A]] =
JsonCodec(encoder(JsonEncoder[A]), decoder(JsonDecoder[A]))
} And the correspondent tests: import zio.json._
import zio.test._
object OptionAsJsonNullTest extends ZIOSpecDefault {
override def spec: Spec[TestEnvironment, Any] = suite("OptionAsJsonNullTest")(
test("property should be emitted as null") {
assertTrue(WillBeNullProperty(None).toJson == """{"property":null}""")
},
test("property should be encoded as nothing") {
assertTrue(WillBeEmptyBody(None).toJson == """{}""")
}
)
case class WillBeEmptyBody(property: Option[Int])
object WillBeEmptyBody {
implicit val jsonCodec: JsonCodec[WillBeEmptyBody] = DeriveJsonCodec.gen
}
case class WillBeNullProperty(property: OptionAsJsonNull[Int])
object WillBeNullProperty {
implicit val jsonCodec: JsonCodec[WillBeNullProperty] = DeriveJsonCodec.gen
}
} |
Thank you very much @alphaho! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello everyone! 👋
First, thank you for a wonderful library and the hard work you put into it 🙂
Continuing #238, I'm not sure how to use a newtype in order to emit
null
instead of nothing when decodingOption[A]
.I thought about doing something like this:
And then implementing an implicit def (like
JsonDecoder.option
), but that didn't compile, and I'm not even sure delegating to the existing option decoder is the right direction.What is the correct way of going about this?
Any help is much appreciated ❤️
The text was updated successfully, but these errors were encountered: