Moshi: кључни концепти, JSON Kotlin библиотека и како ради

Аутор: IT Sectr Објављено: 2026-03-15 Време читања: 8 мин

Moshi је модерна JSON библиотека компаније Square, креирана посебно за Kotlin и Android узимајући у обзир ограничења Gson-а. Потпуно је компатибилна са null-безбедношћу Kotlin-а, генерише код у фази компилације и не користи рефлексију, што повећава перформансе и поузданост. Према подацима Square Moshi, 2024, Moshi обезбеђује предвидљиву серијализацију и подржава прилагођене адаптере за све типове података.

Главно

  • Moshi — JSON библиотека компаније Square за Kotlin и Android без рефлексије
  • Kotlin адаптер — уграђена подршка за data class, подразумеване вредности и null safety
  • @Json — анотација за подешавање имена поља и игнорисање особина
  • Адаптери — прилагођена логика серијализације путем @ToJson и @FromJson
  • Кодогенерација — Moshi генерише адаптере у фази компилације путем kapt или KSP

Шта је Moshi

Moshi је JSON библиотека за JVM, Android и Kotlin Multiplatform, коју је креирао Square (аутори OkHttp и Retrofit). За разлику од Gson-а, Moshi се не ослања на рефлексију — адаптери се генеришу у фази компилације путем анотације @JsonClass(generateAdapter = true). То чини Moshi бржим, безбеднијим и предвидљивијим у раду са Kotlin-специфичним конструкцијама.

Филозофија и предности

Основна разлика Moshi-ја од претходника је одбацивање рефлексије. Рефлексија омогућава Gson-у да ради са било којом класом без припреме, али цена су спора иницијализација, немогућност оптимизације од стране компилатора и ризик од грешака током извршавања. Moshi захтева експлицитно навођење класа за кодогенерацију, али заузврат даје брзину ручно писаног кода и потпуну типску безбедност у фази компилације.

kotlin
// Повезивање Moshi-ја у build.gradle
dependencies {
    implementation "com.squareup.moshi:moshi:1.15.0"
    implementation "com.squareup.moshi:moshi-kotlin:1.15.0"
    kapt "com.squareup.moshi:moshi-kotlin-codegen:1.15.0"
}

// Једноставан модел са кодогенерацијом
@JsonClass(generateAdapter = true)
data class User(
    @Json(name = "user_id")
    val id: Int,
    val name: String,
    val email: String,
    val avatar: String? = null
)

// Коришћење
val moshi = Moshi.Builder()
    .build()
val jsonAdapter = moshi.adapter(User::class.java)

Повезивање и подешавање

За почетак рада са Moshi-јем потребно је додати зависности у build.gradle и анотирати моделе. Moshi.Builder служи као улазнa тачка: кроз њега се додају уграђени адаптери за стандардне типове, прилагођени адаптери и подешава понашање библиотеке. Moshi подржава адаптере за Date, Enum, Collection и Map из кутије, али за Kotlin класе је потребан moshi-kotlin модул. За разлику од Gson-а, Moshi не користи рефлексију за Kotlin класе подразумевано — за то се повезује KotlinJsonAdapterFactory, који служи као резервна опција када се кодогенерација не примењује или класа није анотирана са @JsonClass. Такав приступ гарантује да програмер експлицитно бира између перформанси кодогенерације и флексибилности рефлексије за сваку конкретну класу.

Креирање Moshi-ја и додавање адаптера

Након изградње Moshi-ја путем Builder-а, програмер добија инстанцу Moshi-ја и захтева адаптер за потребну класу. JsonAdapter је централни објекат који обавља серијализацију путем toJson() и десеријализацију путем fromJson(). Moshi аутоматски користи генерисани адаптер ако је класа анотирана са @JsonClass(generateAdapter = true), иначе примењује рефлексивни KotlinJsonAdapterFactory као резервну опцију. Овај приступ комбинује брзину кодогенерације са флексибилношћу рефлексивног механизма за пројекте било које величине и нивоа сложености. Moshi је одличан како за мале апликације, тако и за велике корпоративне пројекте са стотинама модела података.

kotlin
// Подешавање Moshi-ја са KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .add(LocalDateAdapter())
    .build()

// Коришћење адаптера
val adapter = moshi.adapter(User::class.java)

// Серијализација
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)

// Десеријализација
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)

// Рад са листом
val listAdapter = moshi.adapter(
    Types.newParameterizedType(
        List::class.java,
        User::class.java
    )
)

Анотације и адаптери

Moshi користи анотације за подешавање серијализације и подршку прилагођених типова. @Json(name = "...") поставља JSON кључ за поље. @Transient искључује поље из серијализације. @JsonClass(generateAdapter = true) укључује кодогенерацију. За прилагођену логику Moshi пружа анотације @ToJson и @FromJson, које се могу поставити у посебну класу адаптера.

@Json и прилагођени адаптери

Анотација @Json замењује Gson-ов @SerializedName и ради слично: поље kotlinName се повезује са JSON кључем „kotlin_name". За типове које Moshi не уме да серијализује подразумевано (нпр. LocalDate), програмер креира класу са методама @ToJson и @FromJson. Адаптери се региструју путем Moshi.Builder.add() и примењују се глобално или на конкретан тип. Moshi подржава sealed class и полиморфну серијализацију путем @JsonClass са експлицитним навођењем дискриминатора, што омогућава рад са хијерархијама типова у JSON-у без ручне провере поља. При десеријализацији Moshi подразумевано игнорише непознате кључеве у JSON-у, што обезбеђује уназадну компатибилност при додавању нових поља на страни сервера без промене клијентског кода. За отклањање грешака може се укључити строги режим путем failOnUnknown, који избацује изузетак при откривању непознатих кључева.

kotlin
// Прилагођени адаптер за LocalDate
class LocalDateAdapter {

    @ToJson
    fun toJson(date: LocalDate): String {
        return date.format(DateTimeFormatter.ISO_LOCAL_DATE)
    }

    @FromJson
    fun fromJson(dateString: String): LocalDate {
        return LocalDate.parse(dateString)
    }
}

// Модел са Moshi анотацијама
@JsonClass(generateAdapter = true)
data class Event(
    @Json(name = "event_id")
    val id: Int,

    @Json(name = "event_date")
    val date: LocalDate,

    @Transient
    val localCache: String? = null
)

// Регистрација адаптера
val moshi = Moshi.Builder()
    .add(LocalDateAdapter())
    .add(KotlinJsonAdapterFactory())
    .build()

Moshi против Gson-а

Поређење Moshi-ја и Gson-а је често питање при избору JSON библиотеке за Android пројекат. Moshi побеђује у савременом Kotlin развоју захваљујући кодогенерацији, null-безбедности и брзини. Gson остаје актуелан за Java пројекте, заоставштински код и сценарије где је минимална конфигурација важна. Разлика постаје приметна на великим количинама података и сложеним моделима.

Перформансе и безбедност

Тестови перформанси показују да Moshi са кодогенерацијом ради 2-5 пута брже од Gson-а на операцијама серијализације и десеријализације. Кључна предност Moshi-ја је коректно руковање null-безбедношћу Kotlin-а: ако у JSON-у недостаје поље, а у моделу је декларисано као non-null без подразумеване вредности, Moshi избацује изузетак у фази десеријализације, спречавајући скривене грешке.

КарактеристикаGsonMoshi
Механизамрефлексијакодогенерација / рефлексија
Null safetyне узима у обзирпотпуна подршка Kotlin
Брзинасредњависока
Подразумеване вредностине подржаваподржава
Kotlin Multiplatformнеда
Величина библиотеке~240 Kb~150 Kb

Избор између Moshi-ја и Gson-а зависи од контекста пројекта. Нови пројекти на Kotlin-у добијају од Moshi-ја захваљујући типској безбедности и перформансама. Gson остаје разуман избор за подршку Java кода, динамичких JSON структура или када је једноставност повезивања важнија од брзине. За Kotlin Multiplatform, Moshi је једини од два варианта који подржава ову платформу.

При миграцији са Gson-а на Moshi, главне промене се тичу анотација и адаптера. Gson-ов @SerializedName замењује се са @Json(name = "..."), а прилагођени JsonSerializer/JsonDeserializer — паром @ToJson/@FromJson. За моделе са подразумеваним вредностима и nullable пољима, Moshi се понаша предвидљивије: ако у JSON-у недостаје non-null поље без подразумеване вредности, Moshi избацује JsonDataException, спречавајући скривене NPE. Интеграција са Retrofit-ом путем MoshiConverterFactory додаје се једном зависношћу и не захтева промену архитектуре мрежног слоја. За обфускацију путем ProGuard-а или R8 потребно је додати правила очувања @JsonClass-анотираних класа и генерисаних адаптера, иначе ће серијализација бити покварена у релизној верзији. У целини, миграција са Gson-а на Moshi је оправдана у новим Kotlin пројектима где су важне перформансе и типска безбедност.

kotlin
// Поређење серијализације: Gson против Moshi-ја
data class Sample(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

// Gson: ради путем рефлексије
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
    Sample::class.java)
// count = 0 (default), али null-безбедност се не проверава

// Moshi: захтева адаптер, null-безбедност је експлицитна
@JsonClass(generateAdapter = true)
data class SampleMoshi(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

Често постављана питања

Шта је Moshi у Android-у?

Moshi је JSON библиотека компаније Square за Kotlin и Android која користи кодогенерацију уместо рефлексије. Обезбеђује високе перформансе, коректно руковање null-безбедношћу Kotlin-а и компатибилност са Kotlin Multiplatform.

По чему је Moshi бољи од Gson-а?

Moshi надмашује Gson по брзини (2-5 пута бржи захваљујући кодогенерацији), безбедности (узима у обзир null-анотације Kotlin-а) и величини (мањи за ~90 Kb). Moshi такође подржава Kotlin Multiplatform и подразумеване вредности у data class.

Како ради анотација @JsonClass у Moshi-ју?

@JsonClass(generateAdapter = true) налаже Moshi-ју да генерише адаптер за ову класу у фази компилације. Генерисани адаптер обавља серијализацију директно, без рефлексије, што даје максималне перформансе.

Како креирати прилагођени Moshi адаптер?

Креирајте класу са методама анотираним са @ToJson (серијализација) и @FromJson (десеријализација). Региструјте инстанцу путем Moshi.Builder.add(). Moshi ће аутоматски пронаћи и применити адаптер при раду са одговарајућим типом.

Да ли Moshi подржава Kotlin Multiplatform?

Да, Moshi подржава Kotlin Multiplatform од верзије 1.13.0. То га чини јединим популарним JSON решењем за KMP пројекте, омогућавајући коришћење заједничког кода серијализације на свим циљним платформама.

Закључци

  • Moshi — модерна JSON библиотека компаније Square са кодогенерацијом уместо рефлексије
  • @JsonClass — анотација за генерацију адаптера, обезбеђујући брзину ручно писаног кода
  • @Json — подешавање JSON кључева, @Transient — искључивање поља из серијализације
  • @ToJson и @FromJson — једноставан API за прилагођене адаптере било којих типова
  • Null safety — Moshi узима у обзир Kotlin анотације и избацује изузетак при неусаглашености
  • Перформансе — 2-5 пута бржи од Gson-а на операцијама серијализације и десеријализације
  • Kotlin Multiplatform — подршка за KMP за универзални код серијализације

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође