Van Coding
Van Coding

Reputation: 24534

Optional for nullable types?

Is it possible to somehow pass nullable types to Optional? Example:

class X(
    val x: Optional<Int?>
)

why?

I want to serialize this the following way:

X(Optional.of(1)) -> {"x":1}
X(Optional.of(null)) -> {"x":null} // <- throws
X(Optional.empty()) -> {}

notice

I've found out that it's possible to do what I want with double Optional, like this:

class X(
    val x: Optional<Optional<String>>
)

But it'd still be interesting if there's a way with Kotlins nullable types or to know why there's not.

Upvotes: 3

Views: 1232

Answers (1)

Madhu Bhat
Madhu Bhat

Reputation: 15183

Having val x: Optional<Int?> is not advised, as you cannot create an Optional container with a null value in it by its definition, and you would encounter a NPE if you try to create an Optional with Optional.of(null). Optional.of(value) takes in a non-nullable value (doc) and Optional.ofNullable(value) can take in a nullable value, but would return an empty Optional (doc).

If you want to be able to serialize the below way

X(Optional.of(1)) -> {"x":{"present":true}}
X(null) -> {"x":null}

you may define the class as below

class X(
    val x: Optional<Int>?
)

The tricky part is to be able to serialize as below

X(Optional.empty()) -> {}

Since by default, Jackson will serialize it as {"x":{"present":false}}. The only option that you have to avoid that is to register Jdk8Module (source) with jackson-datatype-jdk8 dependency in ObjectMapper by

val mapper = ObjectMapper()
val jdk8Module = Jdk8Module()
jdk8Module.configureAbsentsAsNulls(true)
mapper.registerModule(jdk8Module)

But this would treat an empty Optional as Java null thereby serializing as below

X(Optional.empty()) -> {"x":null}
X(Optional.of(1)) -> {"x":1}

Optional.ofNullable(value) with null as value would behave similar to Optional.empty() as both would return an empty Optional.

The only way to get X(Optional.empty()) -> {} would be by annotating the field with @JsonInclude(JsonInclude.Include.NON_NULL), but that would also mean that you'd get the serialization X(null) -> {}

Upvotes: 1

Related Questions