Moshi 1.9.1 не может сериализовать тип Kotlin

У меня есть рабочий код сериализации / десериализации данных с использованием Moshi 1.8.0

Обновление до 1.9.1 теперь приводит к сбою при попытке сериализации:

java.lang.IllegalArgumentException: невозможно сериализовать тип Kotlin com.xxx.Spot. Отражающая сериализация классов Kotlin без использования kotlin-reflection имеет неопределенное и неожиданное поведение. Пожалуйста, используйте KotlinJsonAdapter из артефакта moshi-kotlin или используйте генерацию кода из артефакта moshi-kotlin-codegen.

Вот код сериализатора:

val moshi = Moshi.Builder().build()
val dataListType = newParameterizedType(List::class.java, T::class.java)
val adapter: JsonAdapter<List<T>> = moshi.adapter(dataListType)
val json = adapter.toJson(dataList)

а соответствующий T-класс -

@IgnoreExtraProperties
data class Spot(
    var id: String = "",
    var localizedName: String? = null,
    var type: String = "",
    var location: Location? = null
)

Я совершенно не понимаю, что здесь делать.

Спасибо за помощь!


person lorenzo    schedule 01.11.2019    source источник
comment
покажите нам зависимости, которые вы используете   -  person coroutineDispatcher    schedule 01.11.2019


Ответы (4)


Вам нужно добавить @JsonClass (generateAdapter = true) перед вашим классом данных

@JsonClass(generateAdapter = true) 
data class Spot(
    var id: String = "",
    var localizedName: String? = null,
    var type: String = "",
    var location: Location? = null
)
person Olle Ekberg    schedule 01.11.2019
comment
Зачем это нужно? - person Morten Holmgaard; 01.11.2019
comment
... и включите соответствующую конфигурацию kapt в свою сборку. Подробности здесь: github.com/square/moshi/blob/master/README .md # котлин - person Jesse Wilson; 02.11.2019
comment
Спасибо, сработало! Добавление @JsonClass (generateAdapter = true) + изменение реализации gradle с moshi на moshi-kotlin + kapt помогло - person lorenzo; 02.11.2019
comment
Даже после использования аннотации JsonClass и попытки использования как метода отражения (реализация moshi-kotlin gradle), так и метода генерации кода Moshi по-прежнему выдавал исключение Cannot Serialize во время выполнения. Были ли у кого-нибудь проблемы даже после внесения этих изменений? - person Cody; 12.08.2020
comment
@Cody - у вас есть перечисления в классе, который вы хотите сериализовать? - person rimes; 08.01.2021
comment
@rimes да, я знаю - person Cody; 08.01.2021
comment
Затем вам нужно исключить их из генерации адаптера. Добавьте это в перечисляемый класс @JsonClass (generateAdapter = false) и добавьте это в файл proguard -keepclassmembers @ com.squareup.moshi.JsonClass class * extends java.lang.Enum {‹fields›; **[] ценности(); } Здесь вы можете прочитать о сериализации перечислений с помощью moshi stackoverflow.com/questions/64068151/ - person rimes; 09.01.2021

Другой вариант, если вы не хотите добавлять аннотации @JsonClass ко всем своим классам данных, - это добавить KotlinJsonAdapterFactory в Moshi Builder.

Moshi.Builder()
    .addLast(KotlinJsonAdapterFactory())
    .build()

Здесь используется отражение, и вам нужно добавить зависимость com.squareup.moshi:moshi-kotlin, как описано здесь https://github.com/square/moshi#kotlin

person miguel    schedule 06.06.2020
comment
Важно отметить, что вам нужно использовать .addLast() вместо .add() для Moshi v1.12 + в соответствии с их документами на github github.com/square/moshi/blob/master/README.md#kotlin - person Cody; 08.05.2021
comment
Спасибо, отредактировал свой ответ. - person miguel; 09.05.2021

Вы можете подавить подстановочные знаки, используя @JvmSuppressWildcards.

нравится

val adapter: JsonAdapter<List<@JvmSuppressWildcards T>> = moshi.adapter(dataListType)
person Khaled Qasem    schedule 09.03.2020

Вы должны добавить эту аннотацию

@JsonClass(generateAdapter = true) 

чтобы ваш класс данных был таким

@JsonClass(generateAdapter = true) 
data class Spot(
        var id: String = "",
        var localizedName: String? = null,
        var type: String = "",
        var location: Location? = null
     )

тогда вы можете использовать расширения Moshi kotlin для десериализации массива json следующим образом:

val Spots: List<Spot>? = yourJson.deserializeList()
person Mazen Rashed    schedule 27.12.2020