#kotlin #serialization #kotlinx.serialization
#kotlin #сериализация #kotlinx.serialization
Вопрос:
Я следовал руководству по созданию пользовательской сериализации для моего универсального класса. Но я все еще сталкиваюсь с ошибкой:
Исключение SerializationException: сериализатор для класса ‘ApiResponse’ не найден. Пометьте класс как @Serializable или явно укажите сериализатор.
Мой класс ApiResponse выглядит следующим образом:
@Serializable(with = ApiResponseSerializer::class)
class ApiResponse<T>(
@SerialName("data")
val data: T? = null,
@SerialName("error")
val error: ApiError? = null
)
И ApiResponseSerializer, который используется в аннотации выше, является:
class ApiResponseSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<ApiResponse<T>> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("ApiResponseDataSerializer") {
val dataDescriptor = dataSerializer.descriptor
element("data", dataDescriptor)
element("error", ApiError.serializer().descriptor)
}
override fun deserialize(decoder: Decoder): ApiResponse<T> =
decoder.decodeStructure(descriptor) {
var data: T? = null
var error: ApiError? = null
loop@ while (true) {
when (val i = decodeElementIndex(descriptor)) {
0 -> data = decodeSerializableElement(descriptor, i, dataSerializer)
1 -> error = decodeSerializableElement(descriptor, i, ApiError.serializer())
CompositeDecoder.DECODE_DONE -> break
else -> throw SerializationException("Unknown index $i")
}
}
ApiResponse(data, error)
}
override fun serialize(encoder: Encoder, value: ApiResponse<T>) {
encoder.encodeStructure(descriptor) {
encodeNullableSerializableElement(descriptor, 0, dataSerializer, value.data)
encodeNullableSerializableElement(descriptor, 1, ApiError.serializer(), value.error)
}
}
}
Затем, когда я пытаюсь сериализовать свой объект данных, я получаю исключение, о котором я упоминал выше.
Json.encodeToString(ApiResponse(data = response.data))
---- OR ----
Json.encodeToString(ApiResponse.serializer(T::class.serializer()), ApiResponse(data = response.data))
Может кто-нибудь сказать мне, где я ошибаюсь? Спасибо.
Комментарии:
1. Отлично работает на моей машине для
Json.encodeToString(ApiResponse(data = "some string"))
. Что это за типresponse.data
? Помечен ли он@Serializable
аннотацией?2. В чем смысл
@loop
label ?3. В моем случае данные могут быть представлены любым классом данных с
@Serializable
аннотацией.@loop
Аннотация появляется в документе. кKSerializer
классу и, насколько я понимаю, отмечает место, куда программа должна возвращаться в случаеbreak
. подробнее: kotlinlang.org/docs/reference / … P.S. теперь это работает. Возможно, это было из-за плохого кэша или чего-то еще. В любом случае спасибо за ваш тест и поддержку
Ответ №1:
Код в вопросе был хорошим, программа завершается сбоем из-за плохого кэша или чего-то еще.
Ответ №2:
Похоже, это ошибка kapt.
Я нашел этот комментарий из репозитория сериализации :
Однако из-за упомянутой проблемы kapt на данный момент это невозможно. Вероятно, жизнеспособным обходным путем может быть перемещение моделей и сериализаторов в отдельный модуль Gradle, который не обрабатывается kapt.
И есть еще вопросы по этой проблеме :
Ответ №3:
kotlinx.serialization использует специальный плагин для создания сериализаторов. Если вы запускаете свой код непосредственно в IDE (например, с помощью main
метода), плагин не используется.
Чтобы убедиться, что сгенерированные сериализаторы доступны в пути к классу, попробуйте вызвать свой код из модульного теста и запустить этот тест с соответствующей задачей Gradle .