decodeElementIndex

abstract fun decodeElementIndex(descriptor: SerialDescriptor): Int(source)

Decodes the index of the next element to be decoded. Index represents a position of the current element in the serial descriptor element that can be found with SerialDescriptor.getElementIndex.

If this method returns non-negative index, the caller should call one of the decode*Element methods with a resulting index. Apart from positive values, this method can return DECODE_DONE to indicate that no more elements are left or UNKNOWN_NAME to indicate that symbol with an unknown name was encountered.

Example of usage:

class MyPair(i: Int, d: Double)

object MyPairSerializer : KSerializer<MyPair> {
    // ... other methods omitted

   fun deserialize(decoder: Decoder): MyPair {
       val composite = decoder.beginStructure(descriptor)
       var i: Int? = null
       var d: Double? = null
       while (true) {
           when (val index = composite.decodeElementIndex(descriptor)) {
               0 -> i = composite.decodeIntElement(descriptor, 0)
               1 -> d = composite.decodeDoubleElement(descriptor, 1)
               DECODE_DONE -> break // Input is over
               else -> error("Unexpected index: $index)
           }
       }
       composite.endStructure(descriptor)
       require(i != null && d != null)
       return MyPair(i, d)
   }
}

This example is a rough equivalent of what serialization plugin generates for serializable pair class.

The need in such a loop comes from unstructured nature of most serialization formats. For example, JSON for the following input {"d": 2.0, "i": 1}, will first read d key with index 1 and only after i with the index 0.

A potential implementation of this method for JSON format can be the following:

fun decodeElementIndex(descriptor: SerialDescriptor): Int {
    // Ignore arrays
    val nextKey: String? = myStringJsonParser.nextKey()
    if (nextKey == null) return DECODE_DONE
    return descriptor.getElementIndex(nextKey) // getElementIndex can return UNKNOWN_NAME
}

If decodeSequentially returns true, the caller might skip calling this method.