Get field names list from case class

后端 未结 6 1687
别跟我提以往
别跟我提以往 2020-11-27 03:31

I need to get only field names of case class. I\'m not interested in its values. I thought getClass.getDeclaredFields.map(_.getName) would return a list of fiel

相关标签:
6条回答
  • 2020-11-27 04:19

    If you are using Spark, this the easiest way to get fields:

    val cols = Seq(CaseClassModel()).toDF().columns
    

    Note: The CaseClassModel should have fields initialized

    0 讨论(0)
  • 2020-11-27 04:21

    Starting Scala 2.13, case classes (which are an implementation of Product) are now provided with a productElementNames method which returns an iterator over their field's names.

    From an instance of the case class (let's say case class Person(name: String, age: Int)), one can retrieve a List of its fields:

    Person("hello", 28).productElementNames.toList
    // List[String] = List(name, age)
    
    0 讨论(0)
  • 2020-11-27 04:31

    If you are also wondering why some Scala-reflection code is not compiling any more, here is a crude solution with the good ol' Java reflection (which, apparently, has been working in exactly the same way since approx. year 1300 BC):

    case class User(b: Int, a: String)
    val u = User(42, "JohnDoe")
    
    classOf[User]
    .getDeclaredFields
    .map{ f => 
      f.setAccessible(true)
      val res = (f.getName, f.get(u))
      f.setAccessible(false)
      res
    }
    

    It will get both the names and the values:

    Array((b,42), (a,bob))
    

    The order seems to be the same as in the constructor.

    0 讨论(0)
  • 2020-11-27 04:34

    Following Andrey Tyukin solution, to get only the list of fields in Scala 2.12:

    val fields: List[String] = classOf[Dummy].getDeclaredFields.map(_.getName).toList
    
    0 讨论(0)
  • 2020-11-27 04:37

    By using User.getClass, you are referring to the class companion object that Scala by default creates for the case class, and not the case class itself. To get the class object of the case class, use classOf[User].

    Alternatively, you could use Scala's reflection API to get the metadata of a case class, which gives you much more information:

    import scala.reflect.runtime.universe._
    
    def classAccessors[T: TypeTag]: List[MethodSymbol] = typeOf[T].members.collect {
      case m: MethodSymbol if m.isCaseAccessor => m
    }.toList
    

    Test in sbt console:

    scala> case class User(name: String, age: Int)
    defined class User
    
    scala> classAccessors[User]
    res0: List[reflect.runtime.universe.MethodSymbol] = List(value age, value name)
    
    0 讨论(0)
  • 2020-11-27 04:38

    User.getClass does not give you the equivalent of User.class in Java, but it gives you the class of the companion object of the User class. You can retrieve the Class object of User with classOf[User].

    edit: Oh and the User$.MODULE$ is an accessor to the singleton instance that is used internally. Think of it as the equivalent to MyClass.INSTANCE when you are writing singletons in Java.

    0 讨论(0)
提交回复
热议问题