-
-
Notifications
You must be signed in to change notification settings - Fork 99
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
Surprising behaviour when deserializing an Option from null when it contains a default value #1130
Comments
@dleblanc First of all using an option that has It will help to find the best suitable solution. As example, if you want to distinguish |
If I pass in an explicit |
@plokhotnyuk can we get an update here? We're not able to adjust the data model unfortunately |
@dleblanc @andyczerwonka @lbryan-citrine Currently, as a workaround you can use a custom codec for the option type together with the case class Ex(opt: Option[String] = Some("hiya"), level: Option[Int] = Some(10))
object CustomOptionCodecs {
implicit val intCodec: JsonValueCodec[Int] = make[Int]
implicit val stringCodec: JsonValueCodec[String] = make[String]
implicit def optionCodec[A](implicit aCodec: JsonValueCodec[A]): JsonValueCodec[Option[A]] =
new JsonValueCodec[Option[A]] {
override def decodeValue(in: JsonReader, default: Option[A]): Option[A] =
if (in.isNextToken('n')) in.readNullOrError(None, "expected 'null' or JSON value")
else {
in.rollbackToken()
Some(aCodec.decodeValue(in, aCodec.nullValue))
}
override def encodeValue(x: Option[A], out: JsonWriter): Unit =
if (x eq None) out.writeNull()
else aCodec.encodeValue(x.get, out)
override def nullValue: Option[A] = None
}
}
import CustomOptionCodecs._
val codecOfEx = make[Ex](CodecMakerConfig.withTransientNone(false)) The need of manual derivation of codecs for concrete types used as Changing of current behavior of |
Thanks for the clarification and work around |
Is there any way to avoid needing to declare the primitive codecs in the body of the custom codec? e.g.
|
With an example case class like:
If I deserialize an optional value with "null", then I get the object built with 'opt' set to None, as expected.
However, if the optional field has a default value:
Then when I deserialize from json with null for that field, I get opt = Some("hiya") instead of None. This seems surprising to me, as I'd expect the default value to apply only when there is no value present for the field, but not when null is explicitly provided.
Is there a combination of configuration parameters I can use to achieve this? All combos of withTransient* didn't seem to help me here.
The text was updated successfully, but these errors were encountered: