Is it possible to get scala case class field's names and types with shapeless?
I've tried like this (T is case class):
trait Cpo[T] {
def withPrimaryKey[R <: HList, K, V <: HList](f: Seq[Symbol] => Seq[Symbol])(
implicit labellGeneric: LabelledGeneric.Aux[T, R], keys: Keys.Aux[R, K],
ktl: hlist.ToList[K, Symbol]): Cpo[T]
}
but I only can get field's name.
Zlaja
Try
object typeablePoly extends Poly1 {
implicit def default[A](implicit typeable: Typeable[A]): Case.Aux[A, String] = at(_ => typeable.describe)
}
trait Cpo[T] {
def withPrimaryKey[R <: HList, K <: HList, V <: HList, V1 <: HList](f: Seq[Symbol] => Seq[Symbol])(implicit
labellGeneric: LabelledGeneric.Aux[T, R],
keys: Keys.Aux[R, K],
ktl: hlist.ToList[K, Symbol],
values: Values.Aux[R, V],
mapper: hlist.Mapper.Aux[typeablePoly.type, V, V1],
vtl: hlist.ToList[V1, String]
): Cpo[T]
}
Now ktl
gives list of field names (as Symbol
s) and vtl
gives list of field types (as String
s).
Try
object typeablePoly extends Poly1 {
implicit def default[A](implicit typeable: Typeable[A]): Case.Aux[A, String] = at(_ => typeable.describe)
}
object nullPoly extends Poly0 {
implicit def default[A]: ProductCase.Aux[HNil, A] = at(null.asInstanceOf[A])
}
trait Cpo[T] {
def withPrimaryKey[R <: HList, K <: HList, V <: HList, V1 <: HList](f: Seq[Symbol] => Seq[Symbol])(implicit
labellGeneric: LabelledGeneric.Aux[T, R],
keys: Keys.Aux[R, K],
ktl: hlist.ToList[K, Symbol],
values: Values.Aux[R, V],
mapper: hlist.Mapper.Aux[typeablePoly.type, V, V1],
fillWith: hlist.FillWith[nullPoly.type, V],
vtl: hlist.ToList[V1, String]
): Cpo[T] = {
println(ktl(keys())) // List('i, 's)
println(vtl(mapper(fillWith()))) // List(Int, String)
???
}
}
case class MyClass(i: Int, s: String)
new Cpo[MyClass] {}.withPrimaryKey(identity)
You definitely can get field names. For example, here you can find how to write your shapeless-based generic derivation mechanism: Bits of shapeless part 2.
More specific, you should look at Deriving case Classes part, there is a function which derives encoder for arbitrary case class, its signature is:
implicit def hconsToJson[Key <: Symbol, Head, Tail <: HList](
implicit key: Witness.Aux[Key],
headWrites: JsonWrites[Head],
tailWrites: JsonWrites[Tail])
: JsonWrites[FieldType[Key, Head] :: Tail] = ???
Hence, key
parameter allows you to acces the field name of the certain field.
For the types, the only known way to me is to use reflection. Read this for details Scala manual on type tags.
If using shapeless is not necessary, you can get the type as well as value using Product class in scala
case class Test(x:Int,y:String,z:Boolean)
println(getGeyNameValueType(Test(1,"a",true)).foreach(println))
def getGeyNameValueType(inp: Product): Iterator[(Any, Class[_])] = {
val itr = inp.productIterator
for {
item <- itr
} yield (item, item.getClass)
}
The output is
(1,class java.lang.Integer)
(a,class java.lang.String)
(true,class java.lang.Boolean)
()