Let’s say we have a Scala method that takes an input param of Map[String, Any], where String is a DB column name and Any is the value.

However the data we need to insert into the DB is in the format of a Scala case class.

How do we convert the case class to a Map for DB insertion?

First let’s compare the input and output:

Existing data structure:

case class LogMessage(date: String, event: String, elapsedTimeMs: Int)

What our DB service requires:

val dbMsg = Map("date" -> "June 3", "event" -> "User Logged In", "elapsedTimeMs" -> 13)

So let’s do the conversion.

Since Scala case classes extend the Product trait, our method signature will accept a Product, and depend on its productIterator implementation.

private def caseClassToMap(obj: Product): Map[String, Any] = {

}

To obtain the “keys” for our map, we will use some standard Java reflection methods:

private def caseClassToMap(obj: Product): Map[String, Any] = {
  val keys = obj.getClass.getDeclaredFields.map(_.getName).toList
}

To obtain the “values” for our map, we will use the productIterator method that our class class implements based on it extending the Product trait:

private def caseClassToMap(obj: Product): Map[String, Any] = {
  val keys = obj.getClass.getDeclaredFields.map(_.getName).toList
  val values = obj.productIterator.toList
}

Now we have extracted our values, we need to zip them together into a map.

private def caseClassToMap(obj: Product): Map[String, Any] = {
  val keys = obj.getClass.getDeclaredFields.map(_.getName).toList
  val values = obj.productIterator.toList

  keys.zip(values).toMap
}

Now we can perform the conversion.

case class LogMessage(date: String, event: String, elapsedTimeMs: Int)

val msg = LogMessage("June 3", "User Logged In", 13)

caseClassToMap(msg)
//=> Map[String,Any] = Map(date -> June 3, event -> User Logged In, elapsedTimeMs -> 13)