core/features/roles/common/src/commonMain/kotlin/dev/inmo/postssystem/features/roles/common/Role.kt

81 lines
2.7 KiB
Kotlin
Raw Normal View History

2021-11-24 07:52:27 +00:00
package dev.inmo.postssystem.features.roles.common
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
@Polymorphic
interface Role {
companion object {
fun serializer(): KSerializer<Role> = RoleSerializer
}
}
2021-11-24 07:52:27 +00:00
@Serializable
2021-11-27 19:11:04 +00:00
data class UnknownRole(val originalJson: JsonElement) : Role
2021-11-24 07:52:27 +00:00
2021-11-27 19:11:04 +00:00
object RoleSerializer : KSerializer<Role> {
2021-11-24 07:52:27 +00:00
private val userRoleFormat = Json { ignoreUnknownKeys = true }
private const val keyField = "key"
private const val valueField = "value"
2021-11-27 19:11:04 +00:00
private val serializers = mutableMapOf<String, KSerializer<out Role>>()
2021-11-24 07:52:27 +00:00
override val descriptor: SerialDescriptor = String.serializer().descriptor
@OptIn(InternalSerializationApi::class)
2021-11-27 19:11:04 +00:00
override fun deserialize(decoder: Decoder): Role {
2021-11-24 07:52:27 +00:00
return if (decoder is JsonDecoder) {
val originalJson = decoder.decodeJsonElement().jsonObject
val type = originalJson[keyField]?.jsonPrimitive ?.content
return if (type == null || !serializers.containsKey(type)) {
2021-11-27 19:11:04 +00:00
UnknownRole(originalJson)
2021-11-24 07:52:27 +00:00
} else {
userRoleFormat.decodeFromJsonElement(
serializers.getValue(type),
originalJson[valueField] ?: buildJsonObject { }
)
}
} else {
val encoded = decoder.decodeString()
userRoleFormat.decodeFromString(this, encoded)
}
}
@InternalSerializationApi
2021-11-27 19:11:04 +00:00
private fun <T : Role> T.toJson(): JsonElement {
2021-11-24 07:52:27 +00:00
return userRoleFormat.encodeToJsonElement(this::class.serializer() as KSerializer<T>, this)
}
@OptIn(InternalSerializationApi::class)
2021-11-27 19:11:04 +00:00
override fun serialize(encoder: Encoder, value: Role) {
2021-11-24 07:52:27 +00:00
if (encoder is JsonEncoder) {
2021-11-27 19:11:04 +00:00
if (value is UnknownRole) {
2021-11-24 07:52:27 +00:00
encoder.encodeJsonElement(value.originalJson)
} else {
val valueSerializer = value::class.serializer()
val type = serializers.keys.first { serializers[it] == valueSerializer }
encoder.encodeJsonElement(
buildJsonObject {
put(keyField, type)
put(valueField, value.toJson())
}
)
}
} else {
encoder.encodeString(
userRoleFormat.encodeToString(this, value)
)
}
}
2021-11-27 19:11:04 +00:00
fun <T : Role> includeSerializer(
2021-11-24 07:52:27 +00:00
type: String,
kSerializer: KSerializer<T>
) { serializers[type] = kSerializer }
fun excludeSerializer(type: String) {
serializers.remove(type)
}
}