Map[String,Object] from a DB (or Key Value store) to a Shapeless Extensible Record
Example:
Lets say I have a map
val fromDB: Map[String, Any] = Map("name" -> "John", "age" -> 25)
Knowing that the field "name" should be a string and the field "age" should be an integer, how would I convert that to a Shapeless Extensible Record as below?
val user = ("name" ->> "John") :: ("age" ->> 25) :: HNil
My end goal is to create an object as below that can convert the Map using the function "fromDB" using the fields.
object User {
object name extends FieldOf[String]
object age extends FieldOf[Int]
def fromDB(data: Map[String,Any]) = {
//TODO
}
}
I'm open to other suggestion and ways of doing this as well. Thanks.
You can use TypeCase
extractors to write this pretty cleanly:
import shapeless._, syntax.singleton._
val StrCase = TypeCase[String]
val IntCase = TypeCase[Int]
def toUserRecord(m: Map[String, Any]) = for {
StrCase(name) <- m.get("name")
IntCase(age) <- m.get("age")
} yield ("name" ->> name) :: ("age" ->> age) :: HNil
Or you could make the casts a little more explicit:
import syntax.typeable._
def toUserRecord(m: Map[String, Any]) = for {
name <- m.get("name").flatMap(_.cast[String])
age <- m.get("age").flatMap(_.cast[Int])
} yield ("name" ->> name) :: ("age" ->> age) :: HNil
Note that I'm returning an Option[LongRecordTypeHere]
to keep this type-safe—if the keys don't exist in the map or the values can't be cast to the right type, we'll get a None
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With