問題

DB(またはキー値ストア)からShapeless Extensible Recordに[String、Object]をマップする

例:

私は地図を持っていると言うことができます

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

フィールド "name"は文字列でなければならず、フィールド "age"は整数でなければならないことを知っています。

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

私の最終目標は、フィールドを使用して関数 "fromDB"を使用してMapを変換できるオブジェクトを以下のように作成することです。

 object User {

  object name extends FieldOf[String]
  object age extends FieldOf[Int]

  def fromDB(data: Map[String,Any]) = {
    //TODO
  }
}
 

私はこれを行う他の提案や方法にもオープンしています。ありがとう。

  ベストアンサー

TypeCase extractorsを使用して、これをきれいに書くことができます。

 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
 

または、キャストをもう少し明示的にすることができます:

 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
 

このタイプセーフを維持するためにOption[LongRecordTypeHere]を返すことに注意してください。キーがマップに存在しない場合、または値を正しいタイプにキャストできない場合は、Noneを取得します。

  同じタグがついた質問を見る

scalashapeless