spark 使用带选项字段的 case class 将数据帧转换为数据集

spark convert dataframe to dataset using case class with option fields

我有以下情况class:

case class Person(name: String, lastname: Option[String] = None, age: BigInt) {}

以及以下 json:

{ "name": "bemjamin", "age" : 1 }

当我尝试将数据框转换为数据集时:

spark.read.json("example.json")
  .as[Person].show()

它向我显示以下错误:

Exception in thread "main" org.apache.spark.sql.AnalysisException: cannot resolve 'lastname' given input columns: [age, name];

我的问题是:如果我的模式是我的情况 class 并且它定义了姓氏是可选的,那么 as() 不应该进行转换吗?

我可以使用 .map 轻松解决此问题,但我想知道是否还有其他更清洁的替代方法。

当您执行 spark.read.json("example.json").as[Person].show() 时,它基本上是将数据帧读取为,

FileScan json [age#6L,name#7]

然后尝试为 Person 对象应用编码器,因此出现 AnalysisException,因为它无法从您的 json 文件中找到 lastname

您可以通过提供一些具有姓氏的数据来暗示姓氏是可选的,或者 试试这个:

val schema: StructType = ScalaReflection.schemaFor[Person].dataType.asInstanceOf[StructType]
val x = spark.read
      .schema(schema)
      .json("src/main/resources/json/x.json")
      .as[Person]
+--------+--------+---+
|    name|lastname|age|
+--------+--------+---+
|bemjamin|    null|  1|
+--------+--------+---+

希望对您有所帮助。

我们还有一个选项可以解决上面的问题 issue.There 需要 2 个步骤

  1. 确保将可能缺失的字段声明为可为空 Scala 类型(如 Option[_])。

  2. 提供模式参数而不依赖于模式 inference.You 可以使用例如使用 Spark SQL 编码器:

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

您可以按如下方式更新代码。

val schema = Encoders.product[Person].schema

val df = spark.read
           .schema(schema)
           .json("/Users/../Desktop/example.json")
           .as[Person]

+--------+--------+---+
|    name|lastname|age|
+--------+--------+---+
|bemjamin|    null|  1|
+--------+--------+---+