在REPL中,为案例类构造函数提供Some(null)
参数不会引起任何意外,该值将保留并分配给案例类的字段:
scala> case class CaseClassWithOptionField(opt:Option[String])
defined class CaseClassWithOptionField
scala> CaseClassWithOptionField(Some(null))
res0: CaseClassWithOptionField = CaseClassWithOptionField(Some(null))
但是,当我将DataFrame映射到字段类型为Option[T]
的案例类时,Some(null)
变成了None
:(我在Jupyter笔记本中运行了此事)>
import sparkSession.implicits._
val someDF = Seq(
(8, Some(null.asInstanceOf[String])),
(64, Some(null.asInstanceOf[String])),
(-27, Some(null.asInstanceOf[String]))
).toDF("id", "opt")
case class CCWithOpt(id: Int, opt: Option[String])
someDF.as[CCWithOpt] take 1 // gives [CCWithOpt(8,None)]
为什么会这样?
答案 0 :(得分:2)
Spark将DataFrame中的Option[T]
类型的列解释为类型nullable
的{{1}}列。例如:
T
请注意,在val df = Seq(
(1, Some("a"), Some(1)),
(2, Some(null), Some(2)),
(3, Some("c"), Some(3)),
(4, None, None)
).toDF("c1", "c2", "c3")
df.show
// +---+----+----+
// | c1| c2| c3|
// +---+----+----+
// | 1| a| 1|
// | 2|null| 2|
// | 3| c| 3|
// | 4|null|null|
// +---+----+----+
df.printSchema
// root
// |-- c1: integer (nullable = false)
// |-- c2: string (nullable = true)
// |-- c3: integer (nullable = true)
列中,c2
与Some(null)
相同。
对于您的None
DataFrame,Spark推断someDF
列为opt
的{{1}}列,并将nullable
视为String
。转换为Some(null.asInstanceOf[String])
后,null
将恢复为Dataset[CCWithOpt]
。