Привет всем, у меня есть следующий код, который я использую для сериализации в строки json для хранения в общих настройках.
interface Serializer {
public fun <T> serialize(data: T, type: Class<T>): String
public fun <T> deserialize(source: String, type: Class<T>): T?
}
Позже я смогу создать реализации этого класса и сериализовать свои объекты с помощью Moshi, как показано ниже.
class SerializerImpl(
private val moshi: Moshi = Moshi.Builder()
.build(),
) : Serializer {
override fun <T> deserialize(source: String, type: Class<T>): T? = try {
moshi.adapter(type).fromJson(source)
} catch (exception: Exception) {
null
}
override fun <T> serialize(data: T, type: Class<T>): String =
moshi.adapter(type).toJson(data)
}
Можете ли вы посоветовать, как перенести эту реализацию на использование сериализации Kotlinx без необходимости менять подпись интерфейса сериализатора? Кажется, мне нужно изменить тип интерфейса сериализатора на использование KSerializer, чтобы это работало, но мне бы очень хотелось этого избежать. что.
Kotlinx.serialization предоставляет экспериментальную поддержку динамического получения сериализаторов (KSerializer) для предоставленных Type или KType. Мы можем использовать его, чтобы легко реализовать Serializer:
class KotlinxSerializer : Serializer {
override fun <T> serialize(data: T, type: Class<T>) = Json.encodeToString(type.serializer(), data)
override fun <T> deserialize(source: String, type: Class<T>) = Json.decodeFromString(type.serializer(), source)
}
@OptIn(ExperimentalSerializationApi::class)
@Suppress("UNCHECKED_CAST")
private fun <T> Class<T>.serializer() = Json.serializersModule.serializer(this) as KSerializer<T>
Использование:
fun main() {
val ser = KotlinxSerializer()
val d1 = MyData("hello")
val s = ser.serialize(d1, MyData::class.java)
println(s) // {"foo":"hello"}
val d2 = ser.deserialize(s, MyData::class.java)
println(d2) // MyData(foo=hello)
}
@Serializable
data class MyData(val foo: String)
Обратите внимание, что нам все равно придется отмечать все классы данных знаком @Serializable. Kotlinx.serialization не может работать без этого, поскольку это платформа сериализации во время компиляции.
@BitwiseDEVS Практически то же самое, но обратите внимание, что мы не можем представить список/карту с параметрами его типа как Class/KClass. Нам нужен Type/KType. Если у вас есть один из них, вы можете использовать почти тот же код, что и выше. Если у вас есть только Class, то это не описывает тип полностью. Если ваш случай не является полностью универсальным и всегда представляет собой список неких универсальных T, то вы можете использовать ListSerializer.
У меня есть идея, как это сделать в Moshi, однако я пока не вижу никакого подхода к сериализации KotlinX, я уже зарегистрировал проблему здесь: github.com/Kotlin/kotlinx.serialization/issues/2720
Знаете ли вы, как сделать это с помощью List и Map?