1
votes

Obtenez le nom et le type du champ de classe de cas avec sans forme

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 commentaires

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


3 Réponses :


0
votes

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>


0 commentaires

4
votes

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 Strings).


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] 
}


1 commentaires

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?



0
votes

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)
}


1 commentaires

Oui, mais il doit avoir une instance de T. Je veux faire cela sans instance. Je l'ai fait avec informe.