从案例类生成Spark StructType / Schema

时间:2016-04-20 13:53:26

标签: apache-spark apache-spark-sql

如果我想在StructType中创建DataFrame.schema(即case class),有没有办法在不创建DataFrame的情况下执行此操作?我很容易做到:

case class TestCase(id: Long)
val schema = Seq[TestCase]().toDF.schema

但是,当我想要的只是架构时,实际创建DataFrame似乎有些过分。

(如果你很好奇,问题背后的原因是我定义了一个UserDefinedAggregateFunction,并且这样做会覆盖几个返回StructTypes的方法并使用case类。)

4 个答案:

答案 0 :(得分:62)

您可以采用与SQLContext.createDataFrame相同的方式执行此操作:

import org.apache.spark.sql.catalyst.ScalaReflection
val schema = ScalaReflection.schemaFor[TestCase].dataType.asInstanceOf[StructType]

答案 1 :(得分:53)

我知道这个问题已经差不多一年了,但我遇到过这个问题并且认为其他人也可能想知道我刚学会使用这种方法:

import org.apache.spark.sql.Encoders
val mySchema = Encoders.product[MyCaseClass].schema

答案 2 :(得分:6)

如果有人想为自定义Java bean执行此操作:

ExpressionEncoder.javaBean(Event.class).schema().json()

答案 3 :(得分:1)

与其手动复制用于创建传递给Encoder的隐式toDF对象的逻辑,不如直接使用它(或更准确地说,以与{{1}相同的方式隐式使用) }):

toDF

不幸的是,这实际上遇到了与使用// spark: SparkSession import spark.implicits._ implicitly[Encoder[MyCaseClass]].schema org.apache.spark.sql.catalyst相同的问题,就像其他答案一样:the Encoder trait是实验性的。

这是如何工作的? Encoders上的toDF方法来自Seq,该方法是通过隐式localSeqToDatasetHolder创建的通过DatasetHolder导入。该函数的定义如下:

spark.implicits._

如您所见,它需要一个implicit def localSeqToDatasetHolder[T](s: Seq[T])(implicit arg0: Encoder[T]): DatasetHolder[T] implicit参数,对于Encoder[T],可以通过newProductEncoder计算(也可以通过{{1}导入) }。我们可以通过方便性的scala.Predef.implicitly(默认情况下,因为它来自case class)来重现此隐式逻辑,以便为案例类获取spark.implicits._,它将仅返回其请求的隐式参数:

Encoder