This PR makes Option[T]s serialize to null or unboxed ts by default. Together with the default configuration of serializeDefaults = false, this allows None fields on case classes to be omitted when serializing case classes. Even with serializeDefaults = true, it still serializes Option[T] as null or unboxed t. Either way is much more in line with standard REST API and JSON schema practices than the current serialization of Option[T] as zero-or-one-element-arrays [] or [t]
Before
After
None
[]
null (or nothing, if a case class field with serializeDefaults = false
Some(1)
[1]
1
Some(None)
[[]]
[null]
Some(Some(1))
[[1]]
[1]
etc.
Despite the convenience, this does mean that there are certain data structures that do not get round tripped. e.g. a field null: Option[T] would get serialized to null, and deserialized as None. This is a tradeoff, but given the rarity of nulls in Scala codebases, and the intuitive expectations of how Options should behave, it seems a reasonable tradeoff.
This PR does make an effort to support nested options: Some(None) is serialized as [null], while Some(Some(t)) is serialized as [t]. This manual boxing allows nested Options to be preserved during round-trip read/write, rather than being flattened out to a single top-level None. These nested options typically do not appear in REST APIs or JSON schemas, and so the choice to preserve round-trip-ability should not affect compatibility with public APIs
This is a breaking change that will need to go into uPickle 4.x. For backwards compatibility, and for migration purposes, the new serialization format is controlled under a flag optionsAsNulls = true. Users who really need the full round-trip preservation of Scala data structures, or who want to preserve compatibility with existing systems, can create a custom config with optionsAsNulls = false. Given the change in the serialization format, I haven't found a way to make uPickle read both old and new formats during the transition, but users can continue to use uPickle 4.x with optionsAsNulls = false indefinitely if they want to preserve compatibility with the old serialization format
For users that want to enable serializeDefaults = true, we should be able to allow serializeDefaults to be configurable on a per-field basis to allow it to be disabled just for the fields typed as Options, to continue eliding them while serializing other default values. Doing that can be done as a follow up
Fixes https://github.com/com-lihaoyi/upickle/issues/528
This PR makes
Option[T]
s serialize tonull
or unboxedt
s by default. Together with the default configuration ofserializeDefaults = false
, this allowsNone
fields oncase class
es to be omitted when serializingcase class
es. Even withserializeDefaults = true
, it still serializesOption[T]
asnull
or unboxedt
. Either way is much more in line with standard REST API and JSON schema practices than the current serialization ofOption[T]
as zero-or-one-element-arrays[]
or[t]
None
[]
null
(or nothing, if acase class
field withserializeDefaults = false
Some(1)
[1]
1
Some(None)
[[]]
[null]
Some(Some(1))
[[1]]
[1]
Despite the convenience, this does mean that there are certain data structures that do not get round tripped. e.g. a field
null: Option[T]
would get serialized tonull
, and deserialized asNone
. This is a tradeoff, but given the rarity ofnull
s in Scala codebases, and the intuitive expectations of howOption
s should behave, it seems a reasonable tradeoff.This PR does make an effort to support nested options:
Some(None)
is serialized as[null]
, whileSome(Some(t))
is serialized as[t]
. This manual boxing allows nestedOption
s to be preserved during round-trip read/write, rather than being flattened out to a single top-levelNone
. These nested options typically do not appear in REST APIs or JSON schemas, and so the choice to preserve round-trip-ability should not affect compatibility with public APIsThis is a breaking change that will need to go into uPickle 4.x. For backwards compatibility, and for migration purposes, the new serialization format is controlled under a flag
optionsAsNulls = true
. Users who really need the full round-trip preservation of Scala data structures, or who want to preserve compatibility with existing systems, can create a custom config withoptionsAsNulls = false
. Given the change in the serialization format, I haven't found a way to make uPickle read both old and new formats during the transition, but users can continue to use uPickle 4.x withoptionsAsNulls = false
indefinitely if they want to preserve compatibility with the old serialization formatFor users that want to enable
serializeDefaults = true
, we should be able to allowserializeDefaults
to be configurable on a per-field basis to allow it to be disabled just for the fields typed asOption
s, to continue eliding them while serializing other default values. Doing that can be done as a follow up