Kotlin Классы данных великолепны; они краткие, они нулевые. Gson тоже хорош; Это де-факто стандарт разбора JSON на Android по уважительной причине. Но! Классы данных, анализируемые с помощью Gson, не гарантируют ни нулевой безопасности, ни даже значений по умолчанию. Или они?

Эта проблема

Есть отличная статья с описанием проблемы. TL; DR, если у вас есть такой класс данных

значения по умолчанию будут проигнорированы, поэтому JSON, например {"intValue":2}, создаст объект {intValue=2,srtValue=null} вместо ожидаемого {intValue=2,srtValue="default"}

Хорошие новости, есть способ исправить это!

Решение

Давайте немного изменим наш класс данных.

Заметили тонкую разницу? Этот класс определяет значения по умолчанию для всех полей. Вот и все! Как только все поля будут иметь значения по умолчанию, Gson будет учитывать их, когда соответствующие поля отсутствуют в JSON (если вам не нужны значения по умолчанию, используйте пустые значения).

Почему это работает?

Причина

Это действительно сводится к двум особенностям.

1. Перегрузки Java Kotlin.

Сравните два класса

байт-код для них будет выглядеть следующим образом Java

как только все поля будут иметь значения по умолчанию, компилятор Kotlin сгенерирует конструктор без параметров по умолчанию в дополнение к другим перегруженным версиям, которые он создает.

2. Небезопасные вызовы Java в Gson

Для Gson важно наличие конструктора по умолчанию. Это работает примерно так (подробнее см. Код ConstructorConstructor):

Это означает, что если вы не укажете создателя экземпляра и в вашем классе нет конструктора по умолчанию, объект будет создан без вызова конструктора. Kotlin помещает в конструктор все проверки на null и значения по умолчанию, поэтому все они будут пропущены.

Итак, если вы хорошо разбираетесь в Gson и еще не готовы перейти к новой библиотеке, которая поддерживает значения Kotlin по умолчанию, такие как Moshi, определите все значения по умолчанию в классах данных и позвольте Остальное сделает Gson.

Это оно? Хорошо…

Предостережение

Приведенное выше решение хорошо работает для JSON с пропущенными полями, но есть еще одна проблема. Обнуляемость, определенная в коде Kotlin, может не соблюдаться в JSON, и Gson не будет жаловаться на JSON, как {"intValue":2,"strValue":null}, который содержит явный null. Если такая ситуация возможна, определите все непримитивные поля как допускающие значение NULL, чтобы избежать неожиданных сбоев в производстве.

Вот и все. Удачного парсинга!