Home > Back-end >  Kotlin: get members of a data class by reflection in the order they have been defined
Kotlin: get members of a data class by reflection in the order they have been defined

Time:11-12

Assume the following simple example data class:

data class SomeDataClass(
  var id: String,
  var name: String,
  var deleted: String
)

With the following code it is possible to get the properties (and set or get their values):

import kotlin.reflect.full.memberProperties

val properties = SomeDataClass::class.memberProperties

print(properties.map { it.name })   // prints:   [deleted, id, name]

The map within the print statement will return a List with the name of the properties in alphabetical order. I need the list in the order they have been defined in the source code, in this case: [id, name, deleted].

It doesn't seem achievable purely through reflection. The only solution I could come up with is to use a helper class defining the order:

val SomeDataClass_Order = listOf("id", "name", "deleted")

This wouldn't be a problem for one or two classes, but it is for hundreds of data classes with the largest one having up to almost one hundred properties.

Any idea would be welcome. I do not need detailed code, rather hints (like parsing the source code, annotations, etc).

CodePudding user response:

If all the properties are declared in the primary constructor, you could "cheat":

val propertyNames = SomeDataClass::class.primaryConstructor!!.parameters.map { it.name }

If you want the KPropertys:

val properties = propertyNames.map { name -> 
    SomeDataClass::class.memberProperties.find { it.name == name } 
}

This unfortunately doesn't find the properties that are declared in the class body.

I don't know about other platforms, but on Kotlin/JVM, the order in which the backing fields for the properties are generated in the class file is not specified, and a quick experiment finds that the order (at least for the version of kotlinc that I'm using right now), the order is the same as the declaration order. So in theory, you could read the class file of the data class, and find the fields. See this related answer for getting the methods in order. Alternatively, you can use Java reflection, which also doesn't guarantee any order to the returned fields, but "just so happens" to return them in declaration order:

// not guaranteed, might break in the future
val fields = SomeDataClass::class.java.declaredFields.toList()

If you do want to get the properties declared inside the class body in order too, I would suggest that you don't depend on the order at all.

  • Related