Search code examples
kotlinserialization

How do I properly serialize an object in Kotlin?


I am trying to serialize certain custom data types. For the simpler ones (like UUID) the approach described in Kotlin Serialization worked great. However I am running into some issues with more complex types. Here is my code:

object class:

@Serializable(with = PairSerializer::class) //error here
private val equipment = mutableListOf<Pair<ItemSlot, ItemStack>>()

serializer class:

class PairSerializer() : KSerializer<Pair<EnumWrappers.ItemSlot, ItemStack>> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("PairEnumISSerializer") {
    }

    override fun serialize(encoder: Encoder, value: Pair<EnumWrappers.ItemSlot, ItemStack>) {
    //implementation
    }

    override fun deserialize(decoder: Decoder): Pair<EnumWrappers.ItemSlot, ItemStack> {
    //implementation
    }
}

here is the error I am getting:

Serializer has not been found for type 'Pair<EnumWrappers.ItemSlot, ItemStack>'. To use context serializer as fallback, explicitly annotate type or property with @Contextual

error image

I can't exactly put

@Serializer(forClass = Pair<EnumWrappers.ItemSlot, ItemStack>::class)

above the serializer class because that shows error: "Only classes are allowed on the left hand side of a class literal" and I haven't been able to find any answers online so far.

  • I tried putting @Serializable above the value that needs to be serialized but that doesn't work.
  • I tried Serializing each type on It's own, but that didn't work.
  • I tried putting @Serializer above the serializer class as I did with the serializer for UUID class, but that doesn't work due to aforementioned error.
  • I tried doing away with mutable list of pairs and using a map. Wrote a new serializer for "ItemStack", and I got basically the same error, just with "ItemStack" instead of the previous one:

Serializer has not been found for type 'ItemStack'. To use context serializer as fallback, explicitly annotate type or property with @Contextual


Solution

  • Update: After some trial and error, this is what finally worked:

    @Serializable(with = PairSerializer::class)
    private val equipment = hashMapOf<ItemSlot,@Serializable(with = ItemStackSerializer::class) ItemStack>()
    

    Essentially, both the list/map need their own serializer as does the custom data type itself