В итоге я реализовал специальный конвертер и фабрику, чтобы правильно подключить его к Genson.
Он использует соглашение метаданных Генсона для представления объекта в виде:
{
"@class": "com.example.ViewModel.Loading"
}
Конвертер предполагает, что useClassMetadata установлен флаг, поэтому при сериализации нужно просто отметить пустой объект. Для десериализации он разрешает имя класса из метаданных, загружает его и получает objectInstance .
object KotlinObjectConverter : Converter<Any> {
override fun serialize(objectData: Any, writer: ObjectWriter, ctx: Context) {
with(writer) {
// just empty JSON object, class name will be automatically added as metadata
beginObject()
endObject()
}
}
override fun deserialize(reader: ObjectReader, ctx: Context): Any? =
Class.forName(reader.nextObjectMetadata().metadata("class"))
.kotlin.objectInstance
.also { reader.endObject() }
}
Чтобы убедиться, что этот преобразователь применяется только к фактическим объектам , я зарегистрировал его, используя фабрику, которая сообщает Genson, когда его использовать и когда следует вернуться к реализации по умолчанию.
object KotlinConverterFactory : Factory<Converter<Any>> {
override fun create(type: Type, genson: Genson): Converter<Any>? =
if (TypeUtil.getRawClass(type).kotlin.objectInstance != null) KotlinObjectConverter
else null
}
Фабрику можно использовать для настройки Genson через builder:
GensonBuilder()
.withConverterFactory(KotlinConverterFactory)
.useClassMetadata(true) // required to add metadata during serialization
// some other properties
.create()
Код, возможно, мог бы быть еще лучше с функцией цепных преобразователей, но у меня еще не было времени проверить это.