如何在Map中的嵌套case类中获取所有类型和列名称

时间:2016-12-02 12:48:49

标签: scala

case class Address( address :String ,pinCode : Int)      

case class Person (a: String,b:Int ,c: Address)

def getClassDefinition[T:TypeTag] =
  (typeOf[T].members.filter(!_.isMethod).map(r  => (r.name -> r.typeSignature)))

val m  = getClassDefinition[Address]

(pinCode ,scala.Int)
(address ,String)    

val p =getClassDefinition[Person]

(c ,A$A332.this.Address)
(b ,scala.Int)
(a ,String)

我正在寻找一个嵌套的结果,而不是直到地址案例类

1 个答案:

答案 0 :(得分:1)

如果我理解了这个问题,那就是获得一个包含名称的类定义 - >类型的每个非方法成员的类型签名对。如果类型签名是标准类型,那就是所需的全部内容;但对于某些类型,需要嵌套定义。我已使用[定义,嵌套定义]或

对这两种情况进行建模

在这个例子中,我选择了一个与包名匹配的isNested(...)规则,但它可以是任何标识类以进行更深入检查的规则。

我不确定输出是否符合您的预期格式,但您可以修改示例代码,也可以将结果映射到您自己的数据结构中。

import scala.reflect.runtime.universe._

object TypeTags {
  // Define your domain name here for the isNested(...) test!
  val myDomainName: String = ???

  // Define some type aliases
  type Definition = ((AnyRef with SymbolApi)#NameType, Type)
  type EitherDefinitionOrNested = Either[Definition, NestedDefinition]

  // A nested definition contains the original definition and an iterable collection of its member definitions (recursively).
  case class NestedDefinition(t: Definition, m: Iterable[EitherDefinitionOrNested])

  // The test to determine if a nested definition is needed.
  def isNested(r: Symbol): Boolean = {
    r.info.typeSymbol.fullName.startsWith(myDomainName)
  }

  // Obtain a class definition from a Symbol.
  def classDefinition(symbol: Symbol): Iterable[EitherDefinitionOrNested] = {
    symbol.typeSignature.members.filter(!_.isMethod).map {
      case r @ nested if isNested(r) => Right(NestedDefinition(nested.name -> nested.typeSignature, classDefinition(nested)))
      case r                         => Left(r.name -> r.typeSignature)
    }
  }

  // Obtain a class definition from a type.
  def getClassDefinition[T: TypeTag]: Iterable[EitherDefinitionOrNested] = classDefinition(typeOf[T].typeSymbol)

  // The test case
  case class Address(address: String ,pinCode: Int)

  case class Person(a: String, b: Int ,c: Address)

  def main(args: Array[String]): Unit = {
    val m = getClassDefinition[Address]
    val p = getClassDefinition[Person]

    println(s"address: $m")
    println(s"person: $p")
  }
}