I'm developing a small library that defines some domain objects as sealed class objects and I'd like to serialize those objects as simple Strings using the kotlinx-serialization library.
The structure of the sealed class with its objects is something like this:
sealed class Domain(val position: UInt, val name: String)
object DomainA : Domain(0u, "Domain A")
object DomainB : Domain(1u, "Domain B")
object DomainC : Domain(2u, "Domain C")
There are more properties inside the objects but they're irrelevant for this question. The other point is that I'm using this sealed class structure to limit the type usage in my domain models with generics. That's why I'm not using simple Enum constants.
To serialize these objects as Strings, as if they were Enum constants, I'm doing the following:
- Adding a new property
serialName
to the object's constructor;
sealed class Domain(val position: UInt, val name: String, val serialName: String)
object DomainA : Domain(0u, "Domain A", "domain-a")
object DomainB : Domain(1u, "Domain B", "domain-b")
object DomainC : Domain(2u, "Domain C", "domain-c")
- Implementing a
fromSerialName()
method to find the appropriate instance in thecompanion object
;
fun fromSerialName(serialName: String): Domain? {
return values.firstOrNull { it.serialName.uppercase() == serialName.trim().uppercase() }
}
This values
field is a listOf()
all Domain
objects that I have to manually update just because of this method.
- Implementing a custom
KSerializer
to handle the serialization process.
object DomainSerializer : KSerializer<Domain> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Domain", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): Domain {
return Domain.fromSerialName(decoder.decodeString())
}
override fun serialize(encoder: Encoder, value: Domain) {
encoder.encodeString(value.serialName)
}
}
The whole point of this question is: Is there any way to do this without all this overhead and make the plugin generate this for me? I'd like to do something like:
@Serializable(with = StringSerializer::class) // or some EnumSerializer::class
sealed class Domain(val position: UInt, val name: String)
@SerialName("domain-a") object DomainA : Domain(0u, "Domain A")
@SerialName("domain-b") object DomainB : Domain(1u, "Domain B")
@SerialName("domain-c") object DomainC : Domain(2u, "Domain C")