Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin reflection - creating objects from CSV

I have a data class named Member:

data class Member(){
    val first_name: String
    val last_name: String
    //30 more

    //a few simple methods
}

I am trying to import a CSV file. Each line of the file contains the fields I want to use to instantiate my Members.

fun ReadCsvFileKotlin() {
    val csvFile = "C:\\Data.csv"
    var memberList = mutableListOf<Member>()
    var reader = File(csvFile).readLines()
    var mbr: Member
    class Member(val p: Int)
    val prop = Member::p
    for(line in reader){
        val mbrProperties = line.split(",")
        for(i in 0..mbrProperties.lastIndex){
            //assign mbrProperties[i] to mbr property
            //mbrProperties[0] = "Bob"
            //mbr.first_name = "Bob"
            //Member::p = mbrProperties[i]
    }
    memberList.add(mbr)
}

I've done my research, but I'm failing to wrap my head around the information I've read and just can't bridge the gap between where I am and where I want to be.

Any advice would be appreciated! Walking me through or giving me examples using my example code would be welcome.

Background: I am automating tests for a website. Prior to executing each test, the member meeting the necessary test criteria is selected from a list, populated from the CSV file. I am looking to create my member objects in this fashion to reduce maintenance overhead as the test scope expands and additional criteria (and Member class fields) are added.

Why am I doing any of this in the manner I am doing? Because I still have much to learn... (So, if you see a better way, please, educate me!)

Thanks!

like image 818
PostPrimeGamer Avatar asked Oct 17 '25 16:10

PostPrimeGamer


2 Answers

The simplest way to solve this is not to use reflection at all. You can pass the property values directly to the class constructor:

data class Member(val firstName: String, val lastName: String)

fun readCsvFileKotlin() {
    // ...
    for (line in reader) {
        val mbrProperties = line.split(",") 
        memberList.add(Member(mbrProperties[0], mbrProperties[1]))
    }
}

If you want to set properties through reflection, you need to declare them as var rather than val, so that they can be changed after the object is created. Then you can use the set method on the property object to change the property value:

data class Member(var firstName: String? = null, var lastName: String? = null)

fun readCsvFileKotlin() {
    // ...
    val prop = Member::firstName
    for (line in reader) { 
        val mbrProperties = line.split(",") 
        val member = Member()
        prop.set(member, mbrProperties[0])
        memberList.add(member)
    }
}
like image 64
yole Avatar answered Oct 19 '25 07:10

yole


If you still look to do that, I created my own CSV library that uses reflection to instantiate POJOs directly from the CSV input and manages errors in the CSV much better than regular parsers I tested, called Kotlin CSV Stream

I actually created it after giving up on traditional parsers because they all did not fill my needs.

like image 22
Sunny Pelletier Avatar answered Oct 19 '25 06:10

Sunny Pelletier