В статье рассказывается:
- Сериализация от Kotlin
- Сериализация от Kotlin + Retrofit
-
Пройди тест и узнай, какая сфера тебе подходит:
айти, дизайн или маркетинг.Бесплатно от Geekbrains
Любой Android-разработчик рано или поздно сталкивается с форматом представления данных типа JSON. Наиболее часто он используется для передачи/получения данных с какого-либо сервера. Формат предельно прост, подробнее о нём можно почитать в Википедии:
«JSON (JavaScript Object Notation, обычно произносится как /ˈdʒeɪsən/ JAY-sən) — текстовый формат обмена данными, основанный на JavaScript. Как и многие другие текстовые форматы, JSON легко читается людьми. Несмотря на происхождение от JavaScript, формат считается независимым от языка и может использоваться практически с любым языком программирования. Для многих языков существует готовый код для создания и обработки данных в формате JSON».
входят в ТОП-30 с доходом
от 210 000 ₽/мес
Скачивайте и используйте уже сегодня:
Топ-30 самых востребованных и высокооплачиваемых профессий 2023
Поможет разобраться в актуальной ситуации на рынке труда
Подборка 50+ бесплатных нейросетей для упрощения работы и увеличения заработка
Только проверенные нейросети с доступом из России и свободным использованием
ТОП-100 площадок для поиска работы от GeekBrains
Список проверенных ресурсов реальных вакансий с доходом от 210 000 ₽
Любой класс в Java или Kotlin можно представить в виде структуры JSON, где есть поля, атрибуты, фигурные скобки обозначают объект, квадратные скобки — массив.
Следующий пример показывает JSON-представление данных об объекте, описывающем человека. В данных присутствуют строковые поля имени и фамилии, информация об адресе и массив, содержащий список телефонов. Как видно из примера, значение может представлять собой вложенную структуру:
{
"firstName": "Иван",
"lastName": "Иванов",
"address": {
"streetAddress": "Московское ш., 101, кв.101",
"city": "Ленинград",
"postalCode": 101101
},
"phoneNumbers": [
"812 123-1234",
"916 123-4567"
]
}
Наиболее популярный среди разработчиков способ трансформировать данные в JSON и обратно — это библиотека GSON от самих разработчиков Google. Она очень проста в использовании, мало весит и интегрирована во многие библиотеки.
На данный момент все, за редким исключением, Android-разработчики используют Kotlin, а GSON (как и другие подобные библиотеки типа Jackson или Moshi) написана на Java. Это не страшно, потому что Kotlin и Java полностью взаимозаменяемы, но есть небольшие нюансы, которые могут привести к совершенно неожиданным результатам.
Скачать файл
Давайте создадим класс User и посмотрим на эти нюансы на практике. В этом классе у нас будут обычные поля и поля со значениями по умолчанию. Как вы знаете, в Java нельзя присваивать переменным значения по умолчанию, а в Kotlin можно:
data class User(
val name: String,
val email: String,
val age: Int = 13,
val role: Role = Role.Viewer
)
enum class Role { Viewer, Editor, Owner }
И теперь представим, что с какого-то сервера пришли данные о пользователе в формате JSON:
{
"name" : "John Doe",
"email" : "john.doe@email.com"
}
Теперь нам нужно распарсить этот JSON и превратить его в обычный класс Kotlin с помощью библиотеки GSON. Добавим зависимость GSON в наш проект в файл Gradle
implementation ‘com.google.code.gson:gson:2.8.6’
и сразу напишем тест:
class JsonUnitTest {
private val jsonString = """
{
"name" : "John Doe",
"email" : "john.doe@email.com"
}
"""
@Test
fun gsonTest() {
val user = Gson().fromJson(jsonString, User::class.java)
assertEquals("John Doe",user.name)
assertEquals(null, user.role)
assertEquals(0, user.age)
//User(name=John Doe, email=john.doe@email.com, age=0, role=null)
}
}
Тест прекрасно выполняется без единой ошибки, то есть код работает. Но обратите внимание, что возраст пользователя у нас == 0, а его роль не определена, хотя в самом классе у нас прописаны значения по умолчанию для этих переменных. Если эти параметры не определены в JSON, должны подставляться значения по умолчанию: возраст == 13, а роль == Viewer, но они не подставляются, а код всё равно работает. Вот так неожиданность! Не такого поведения мы ожидали!
на обучение «Android-разработчик» до 14 декабря
Давайте разбираться. Дело в том, что, как мы писали выше, библиотека GSON написана на Java, а это значит, что значения по умолчанию для несуществующих полей такие: для примитива int — это 0, для отсутствующего объекта — это null. Простая трансформация JSON в класс на Kotlin может легко сломать null-safety, на который так рассчитывают все разработчики, и может привести к падению приложения там, где оно падать не должно.
И тут нам на помощь приходит котлиновская библиотека по сериализации объектов.
Сериализация от Kotlin
Это небольшая вспомогательная библиотечка от разработчиков языка, которая работает с помощью аннотации @Serializable. С ней у вас не будет проблем при использовании полей по умолчанию. Чтобы подключить библиотеку к своему проекту, нужно прописать в файле Gradle плагин и несколько зависимостей. В файле проекта build.gradle(Project):
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
classpath "org.jetbrains.kotlin:kotlin-serialization:1.5.31"
}
}
В файле проекта build.gradle(Module:app):
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlinx-serialization'
}
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0"
}
Теперь трансформация JSON (сериализация) будет проходить корректно. Напишем наш класс и добавим аннотацию:
@Serializable
data class User(
val name: String,
val email: String,
val age: Int = 13,
val role: Role = Role.Viewer
)
enum class Role { Viewer, Editor, Owner }
Протестируем:
class JsonUnitTest {
private val jsonString = """
{
"name" : "John Doe",
"email" : "john.doe@email.com"
}
""".trimIndent()
@Test
fun gsonTest() {
val user = Gson().fromJson(jsonString, User::class.java)
assertEquals("John Doe", user.name)
assertEquals(null, user.role)
assertEquals(0, user.age)
//User(name=John Doe, email=john.doe@email.com, age=0, role=null)
}
@Test
fun jsonTest() {
val user = Json.parse(User.serializer(), jsonString)
assertEquals("John Doe", user.name)
assertEquals(Role.Viewer, user.role)
assertEquals(13, user.age)
//User(name=John Doe, email=john.doe@email.com, age=13, role=Viewer)
}
}
Тест пройден успешно! Теперь класс сериализуется у нас со значениями по умолчанию, если таковые прописаны в классе.
ТОП-100 площадок для поиска работы от GeekBrains
20 профессий 2023 года, с доходом от 150 000 рублей
Чек-лист «Как успешно пройти собеседование»
Сериализация от Kotlin + Retrofit
Если вы хоть раз отправляли запрос на сервер или получали с сервера какой-то ответ, то наверняка вы знакомы с библиотекой Retrofit. В этой библиотеке нет поддержки сериализации от Kotlin, но у вас есть возможность добавить вспомогательную библиотеку от Джека Вортона в качестве зависимости Gradle:
dependencies {
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
}
Теперь при использовании Retrofit сериализация будет происходить автоматически:
val contentType = "application/json".toMediaType()
val retrofit = Retrofit.Builder()
.baseUrl("https://www.example.com")
.addConverterFactory(Json(JsonConfiguration(strictMode = false)).asConverterFactory(contentType))
.build()
Дополнительно, но не обязательно вы можете использовать JsonConfiguration для выключения StrictMode. StrictMode включен по умолчанию и запрещает использование неизвестных ключей в JSON и нечисловые значения в числах с плавающей точкой. Хорошая практика — включать StrictMode в «дебажной» версии приложения и выключать его в «релизной».
Читайте больше полезных статей для начинающих Android-разработчиков:
- «Эксперименты с новыми API Android 12: Render Effect»
- «Android 12: пристальный разбор главных фич»
- «Эксперименты с новыми API Android 12: Splash Screen»
- «Гайд по отладке Android-приложения: ищем баги и читаем логи»
А если затянет — приходите на факультет Android-разработки. В время учебы вы разработаете Android-приложение и выложите его в Google Play, даже если никогда не программировали. А также своите языки Java и Kotlin, командную разработку, Material Design и принципы тестирования.