Hello, is there any best practises for data struct...
# serialization
a
Hello, is there any best practises for data structure migration? I have a simple enum class
Copy code
@Serializable
sealed interface FieldType

@Serializable
public enum class PrimitiveType: FieldType {
    String,
    Boolean
}
with custom serializer
Copy code
buildClassSerialDescriptor("PrimitiveType") { element("name", String.serializer().descriptor) } // {"value":["PrimitiveType",{"name":"String"}]}
now I want to migrate all my previous json to new structure
Copy code
PrimitiveSerialDescriptor("primitiveType", STRING) // {"value":["PrimitiveType","String"]}
Is there a way to achieve that? May be some custom serialization tips like try to decode with oldDescriptor and if it fails decode with new descriptor?
e
you can wrap your serializer in a custom subclass of https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-transforming-serializer/ which converts from one form to the other, e.g.
Copy code
class UnwrapEnumSerializer<E : Enum<E>>(kSerializer: KSerializer<E>) : JsonTransformingSerializer<E>(kSerializer) {
    override fun transformDeserialize(element: JsonElement): JsonElement =
        if (element is JsonObject) element.jsonObject["name"] ?: JsonNull else element
}
👀 1
although if you have a custom serializer to begin with, you could build support directly into it,
Copy code
object PrimitiveTypeSerializer : KSerializer<PrimitiveType> {
    override val descriptor: SerialDescriptor =
        SerialDescriptor("PrimitiveType", JsonElement.serializer().descriptor)

    override fun deserialize(decoder: Decoder): PrimitiveType {
        val jsonName = when (val jsonElement = (decoder as JsonDecoder).decodeJsonElement()) {
            is JsonPrimitive -> jsonElement
            is JsonObject -> jsonElement["name"]
            else -> null
        }
        if (jsonName is JsonPrimitive && jsonName.isString) {
            return PrimitiveType.valueOf(jsonName.content)
        } else {
            throw SerializationException()
        }
    }

    override fun serialize(encoder: Encoder, value: PrimitiveType) {
        encoder.encodeString(value.name)
    }
}