blackmo18/kotlin-grass

Improve handling of missing target fields in CSV

Opened this issue · 2 comments

I was recently parsing a CSV into a target class, where one of the fields of said class wasn't present in the CSV. This resulted in this exception being thrown:

java.lang.ClassCastException: Cannot cast kotlin.Unit to java.lang.String

Upon further analysis this seems to happen because when creating the array of parameters for the constructor of the target class in
Root.kt an empty default value block is specified (the Unit in the exception).

I think this is a corner case with no clear-cut solution, at the same time I think the behaviour towards the user could be improved (it took me a debugging session to understand what was going on).

A couple of ideas:

  • setting null as the default value for constructor parameters. Since anyway the type of actualParams is Array<Any?> this wouldn't cause any inconsistency or incompatibility, allowing for target classes with optional parameters not present in the source CSV to still be initialized correctly
  • doing a pass over the same array and remove all the values that have Unit type. This would allow two useful things: supporting target classes with default values on parameters that might not be in the source CSV, and otherwise showing a more meaningful error to the user (as in this case, the final actualParams won't have a required argument, hence resulting in Kotlin reflection to clearly state which field is missing rather than throwing the more generic ClassCastException)

For now I can solve the problem in my code by removing the offending fields, but I'd love to help alleviate this problem.
Please let me know your thoughts, I'd be happy to PR a solution afterwards.

Can you provide a sample csv file and data class you are using.

Version of kotlin grass and kotlin-csv?

Tho it should throw MissMatchedNumberOfFieldsException if csv length and number fields of data class.

This gist reproduces the problem for me (sorry I might have forgotten that I'm setting ignoreUnknownFields).

Here's an excerpt from the Gradle configuration of the project with all relevant dependencies and versions:

  implementation("com.github.doyaaaaaken:kotlin-csv-jvm:0.15.2")
  implementation("io.github.blackmo18:kotlin-grass-core-jvm:1.0.0")
  implementation("io.github.blackmo18:kotlin-grass-parser-jvm:0.8.0")