Необязательный для обнуляемых типов? - PullRequest
2 голосов
/ 23 января 2020

Можно ли как-нибудь передать обнуляемые типы в Optional? Пример:

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

почему?

Я хочу сериализовать это следующим образом:

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

уведомление

Я обнаружил, что с двойной опцией Optional можно делать то, что я хочу, например:

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

Но все равно было бы интересно, если есть способ с обнуляемыми типами Kotlins или узнать, почему нет.

1 Ответ

1 голос
/ 23 января 2020

Наличие val x: Optional<Int?> не рекомендуется, поскольку вы не можете создать дополнительный контейнер с значением null в его определении, и вы встретите NPE, если попытаетесь создать дополнительный с Optional.of(null). Optional.of(value) принимает необнуляемое значение ( do c), а Optional.ofNullable(value) может принимать обнуляемое значение, но возвращает пустое Optional ( do c).

Если вы хотите иметь возможность сериализовать следующий способ

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

, вы можете определить класс следующим образом

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

Сложная часть чтобы иметь возможность сериализации, как показано ниже

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

Так как по умолчанию Джексон будет сериализовать его как {"x":{"present":false}}. Единственный вариант, который вы должны избегать, это зарегистрировать Jdk8Module ( source ) с jackson-datatype-jdk8 зависимостью в ObjectMapper от

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

Но это будет относиться к пустому как Java null, тем самым сериализуя, как показано ниже

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

Optional.ofNullable(value) с null, так как value будет вести себя подобно Optional.empty(), так как оба вернут пустой Optional.

Единственный способ получить X(Optional.empty()) -> {} - это пометить поле с помощью @JsonInclude(JsonInclude.Include.NON_NULL), но это также будет означать, что вы получите сериализацию X(null) -> {}

...