Почему JsonNull в GSON?

Документы говорят, что метод JsonObject # get возвращает значение null, если такой член не существует. Это неточно; иногда вместо null возвращается объект JsonNull.

Какова идиома для проверки того, существует ли конкретное поле в GSON? Я хочу избежать этого неуклюжего стиля:

jsonElement = jsonObject.get("optional_field");
if (jsonElement != null && !jsonElement.isJsonNull()) {
    s = jsonElement .getAsString();
}

Почему GSON использовал JsonNull вместо null?

Существует ответ , что - различия между null и JsonNull. В моем вопросе выше я ищу причины, по которым.

Ответ 1

Гссон, по-видимому, хотел смоделировать разницу между отсутствием значения и наличием значения JSON null в JSON. Например, существует разница между этими двумя фрагментами JSON

{}
{"key":null}

ваше приложение может считать их одинаковыми, но формат JSON не поддерживает.

Вызов

JsonObject jsonObject = new JsonObject(); // {}
jsonObject.get("key");

возвращает значение Java null, поскольку ни один член не существует с этим именем.

Вызов

JsonObject jsonObject = new JsonObject();
jsonObject.add("key", JsonNull.INSTANCE /* or even null */); // {"key":null}
jsonObject.get("key");

возвращает экземпляр типа JsonNull (singleton, на который ссылается JsonNull.INSTANCE), потому что член существует с этим именем, и его значение равно JSON null, представленное значением JsonNull.

Ответ 2

Я знаю, что вопрос не требует решения, но я пришел сюда в поисках одного. Поэтому я опубликую это на тот случай, если это кому-то понадобится.

Ниже код расширения Kotlin избавляет от необходимости проверять null и isJsonNull отдельно для каждого элемента.

import com.google.gson.JsonElement
import com.google.gson.JsonObject


fun JsonObject.getNullable(key: String): JsonElement? {
    val value: JsonElement = this.get(key) ?: return null

    if (value.isJsonNull) {
        return null
    }

    return value
}

и вместо того, чтобы звонить, как это

jsonObject.get("name")

ты так называешь

jsonObject.getNullable("name")

Работы особенно создают во вложенных структурах. Ваш код в конечном итоге будет выглядеть так

val name = jsonObject.getNullable("owner")?.asJsonObject?.
    getNullable("personDetails")?.asJsonObject?.
    getNullable("name") 
    ?: ""