使用 shapeless 获取 case class 字段的名称和类型
Get case class field's name and type with shapeless
是否可以使用 shapeless 获取 scala case class 字段的名称和类型?
我试过这样(情况是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]
}
但我只能得到字段的名称。
兹拉亚
你绝对可以获得字段名。例如,在这里您可以找到如何编写基于无形的泛型派生机制:Bits of shapeless part 2。
更具体地说,你应该看看 Deriving case 类 部分,有一个函数可以为任意情况 class 导出编码器,它的签名是:
implicit def hconsToJson[Key <: Symbol, Head, Tail <: HList](
implicit key: Witness.Aux[Key],
headWrites: JsonWrites[Head],
tailWrites: JsonWrites[Tail])
: JsonWrites[FieldType[Key, Head] :: Tail] = ???
因此,key
参数允许您访问特定字段的字段名称。
对于类型,我唯一知道的方法是使用反射。阅读本文了解详情 Scala manual on type tags。
尝试
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]
}
现在 ktl
给出字段名称列表(如 Symbol
s),vtl
给出字段类型列表(如 String
s)。
尝试
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)
如果不需要使用 shapeless,您可以在 scala
中使用 Product class 获取类型和值
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)
}
输出是
(1,class java.lang.Integer)
(a,class java.lang.String)
(true,class java.lang.Boolean)
()
是否可以使用 shapeless 获取 scala case class 字段的名称和类型?
我试过这样(情况是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]
}
但我只能得到字段的名称。
兹拉亚
你绝对可以获得字段名。例如,在这里您可以找到如何编写基于无形的泛型派生机制:Bits of shapeless part 2。 更具体地说,你应该看看 Deriving case 类 部分,有一个函数可以为任意情况 class 导出编码器,它的签名是:
implicit def hconsToJson[Key <: Symbol, Head, Tail <: HList](
implicit key: Witness.Aux[Key],
headWrites: JsonWrites[Head],
tailWrites: JsonWrites[Tail])
: JsonWrites[FieldType[Key, Head] :: Tail] = ???
因此,key
参数允许您访问特定字段的字段名称。
对于类型,我唯一知道的方法是使用反射。阅读本文了解详情 Scala manual on type tags。
尝试
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]
}
现在 ktl
给出字段名称列表(如 Symbol
s),vtl
给出字段类型列表(如 String
s)。
尝试
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)
如果不需要使用 shapeless,您可以在 scala
中使用 Product class 获取类型和值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)
}
输出是
(1,class java.lang.Integer)
(a,class java.lang.String)
(true,class java.lang.Boolean)
()