2017年06月09日

case classとList, Map変換

shapelessでcase class -> List, Mapへの変換

case class Foo(a: String, b: Int, c: Long)
val foo = Foo("test", 1, 2)

こちらのコードをshapelessを使ってList, Mapへ変換してみます。

※shapelessを簡単にREPLで使うには

curl -s https://raw.githubusercontent.com/milessabin/shapeless/master/scripts/try-shapeless.sh | bash

Listへの変換

Generic の力を借りてcase class -> HListとすることでListに変換できます。

import shapeless._
import shapeless.ops.hlist.ToTraversable

def caseClassToList[A, R <: HList, V](a: A)(implicit gen: Generic.Aux[A, R], toList: ToTraversable.Aux[R, List, V]): List[Any] = gen.to(a).toList

caseClassToList(foo)

res1: List[Any] = List(test, 1, 2)

Mapへの変換

Mapの場合は、keyの情報が必要になるので LabelledGeneric を使って変換します。

import shapeless._
import shapeless.ops.record.ToMap

def caseClassToMap[A, R <: HList, K, V](a: A)(implicit gen: LabelledGeneric.Aux[A, R], toMap: ToMap.Aux[R, K, V]): Map[Symbol, Any] = {
  toMap(gen.to(a)).map {
    case (a: Symbol, b) => (a, b)
  }
}
caseClassToMap(foo)

res1: Map[Symbol, Any] = Map('c -> 2, 'b -> 1, 'a -> test)

まとめ

HListに変換することで、任意の型へ変換の非常に便利です。

RELATED POSTS