Map [String, Object] from a database (or key store) into a Shapeless Extensible Record

Map [String, Object] from a database (or key store) into a Shapeless Extensible Record

Example:

Let's say I have a map

val fromDB: Map[String, Any] = Map("name" -> "John", "age" -> 25) 

Knowing that the "name" field should be a string, and the "age" field should be an integer, how would I convert this to a Shapeless Extensible Record, as shown below?

 val user = ("name" ->> "John") :: ("age" ->> 25) :: HNil 

My ultimate goal is to create an object, as shown below, that can transform a map using the "fromDB" function using fields.

 object User { object name extends FieldOf[String] object age extends FieldOf[Int] def fromDB(data: Map[String,Any]) = { //TODO } } 

I am open to other suggestions and ways to do this. Thanks.

+7
scala shapeless
source share
1 answer

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 can make the throws 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 am returning Option[LongRecordTypeHere] to preserve this type of security - if the keys do not exist on the map or the values ​​cannot be cast to the correct type, we will get None .

+10
source share

All Articles