Est-il possible d'obtenir les noms et les types des champs de classe de cas scala avec shapeless?
J'ai essayé comme ça (T est la classe de cas):
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] }
mais Je ne peux obtenir que le nom du champ.
Zlaja
3 Réponses :
Vous pouvez certainement obtenir des noms de champs. Par exemple, vous pouvez trouver ici comment écrire votre mécanisme de dérivation générique sans forme: Bits de la partie informe 2 . Plus précisément, vous devriez regarder la partie Dérivation des classes de cas , il existe une fonction qui dérive un encodeur pour une classe de cas arbitraire, sa signature est:
implicit def hconsToJson[Key <: Symbol, Head, Tail <: HList]( implicit key: Witness.Aux[Key], headWrites: JsonWrites[Head], tailWrites: JsonWrites[Tail]) : JsonWrites[FieldType[Key, Head] :: Tail] = ???
Par conséquent, key
vous permet d'accéder au nom de champ du certain champ.
Pour les types, le seul moyen connu pour moi est d'utiliser la réflexion. Lisez ceci pour plus de détails Manuel Scala sur les balises de type . p>
Essayez
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)
Maintenant ktl
donne la liste des noms de champs (sous forme de Symbol
s) et vtl
donne la liste des types de champs (comme String
s).
Essayez
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] }
Si j'ai bien compris, pour obtenir des types de champs, j'ai besoin d'une instance de T? Est-il possible d'obtenir des types de champs simplement en utilisant le type T?
Si l'utilisation de sans forme n'est pas nécessaire, vous pouvez obtenir le type ainsi que la valeur en utilisant la classe Product dans scala
(1,class java.lang.Integer) (a,class java.lang.String) (true,class java.lang.Boolean) ()
Le résultat est
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) }
Oui, mais il doit avoir une instance de T. Je veux faire cela sans instance. Je l'ai fait avec informe.
Est-il nécessaire d'utiliser informe? Demander parce que vous pouvez facilement le faire avec la classe de produit
@Shantiswarup, un exemple?
J'ai ajouté l'exemple de code comme réponse à cette question