I have a csv file and a case class that models each row of the csv file.
However, it is cumbersome to initialize a case class with many attributes.
For a example, given a case class such as below,
case class Airline(
airline: String,
avail_seat_km_per_week: Long,
incidents_85_99: Int,
fatal_accidents_85_99: Int,
fatalities_85_99: Int,
incidents_00_14: Int,
fatal_accidents_00_14: Int,
fatalities_00_14: Int
)
I have to write a function like this to initialize the case class
def parse(row: Seq[String]) = {
Airline(
row(0),
row(1).toLong,
row(2).toInt,
row(3).toInt,
row(4).toInt,
row(5).toInt,
row(6).toInt,
row(7).toInt
)
}
Since this kind of situation frequently occurs for my project, I thought it would be nice to have a function to convert a List of String to a case class with the correct type in a type-safe manner.
I noticed that what I’m trying to do is to make an inverse function of the function described here, so I followed this approach.
Here is what I made so far.
trait FieldDecoder[A]:
def decodeField(a: String): A
trait RowDecoder[A <: Tuple]:
def decodeRow(a: Row): A
given FieldDecoder[Int] with
def decodeField(x: String) = x.toInt
given FieldDecoder[Boolean] with
def decodeField(x: String) = x.toBoolean
given FieldDecoder[Long] with
def decodeField(x: String) = x.toLong
given FieldDecoder[String] with
def decodeField(x: String) = x
given RowDecoder[EmptyTuple] with
def decodeRow(row: Row) = EmptyTuple
given [H: FieldDecoder, T <: Tuple: RowDecoder]: RowDecoder[H *: T] with
def decodeRow(row: Row) =
summon[FieldDecoder[H]].decodeField(row.head) *: summon[RowDecoder[T]]
.decodeRow(row.tail)
def csvToTuple[X <: Tuple: RowDecoder](row: Row): X =
summon[RowDecoder[X]].decodeRow(row)
The code compiles, and I wrote a test
@Test def testcsvToTuple(): Unit = {
assertEquals(
(42, true, "Hello"),
csvToTuple(List("42", "true", "Hello"))
)
}
However this fails; csvToTuple
produces a empty tuple.
java.lang.AssertionError:
Expected :(42,true,Hello)
Actual :()
I wonder where I went wrong?
The current code I implemented is here, which also includes conversion from tuple to List of String ( I got nice help in this topic)