在scala中基于字符串的select case类

eanckbw9  于 2021-05-29  发布在  Spark
关注(0)|答案(4)|浏览(331)

如何选择一个 case class 基于 String 价值?
我的密码是

val spark = SparkSession.builder()...
val rddOfJsonStrings: RDD[String] = // some json strings as RDD
val classSelector: String = ??? // could be "Foo" or "Bar", or any other String value
case class Foo(foo: String)
case class Bar(bar: String)

if (classSelector == "Foo") {
  val df: DataFrame = spark.read.json(rddOfJsonStrings)
  df.as[Foo]
} else if (classSelector == "Bar") {
  val df: DataFrame = spark.read.json(rddOfJsonStrings)
  df.as[Bar]
} else {
  throw ClassUnknownException //custom Exception
}

变量 classSeletector 是一个简单字符串,应用于指向同名的case类。
想象一下我不仅仅有 Foo 以及 Bar 作为案例类,但不止这两个。怎么可能叫警察 df.as[] 基于字符串的语句(如果可能的话)?
或者在scala中有完全不同的方法吗?

jucafojl

jucafojl1#

备选方案-

亮点-
使用 simpleName 是case类的,而不是伴随对象的
如果 classSelectornull ,解决方案不会失败

case class Foo(foo: String)
case class Bar(bar: String)

测试用例-

val rddOfJsonStrings: RDD[String] = spark.sparkContext.parallelize(Seq("""{"foo":1}"""))
    val classSelector: String = "Foo" // could be "Foo" or "Bar", or any other String value

    val ds = classSelector match {
      case foo if classOf[Foo].getSimpleName == foo =>
        val df: DataFrame = spark.read.json(rddOfJsonStrings)
        df.as[Foo]
      case bar if classOf[Bar].getSimpleName == bar =>
        val df: DataFrame = spark.read.json(rddOfJsonStrings)
        df.as[Bar]
      case _ => throw new UnsupportedOperationException
    }

    ds.show(false)

    /**
      * +---+
      * |foo|
      * +---+
      * |1  |
      * +---+
      */
yh2wf1be

yh2wf1be2#

定义一个泛型方法并调用它,

getDs[Foo](spark,rddOfJsonStrings)
getDs[Bar](spark,rddOfJsonStrings)

def getDs[T](spark : SparkSession, rddOfJsonStrings:String)  {
    spark.read.json(rddOfJsonStrings).as[T](Encoders.bean[T](classOf[T]))
  }
frebpwbc

frebpwbc3#

检查以下代码

classSeletector match {
    case c if Foo.getClass.getSimpleName.replace("$","").equalsIgnoreCase(c) =>  spark.read.json(rddOfJsonStrings).as[Foo]
    case c if Bar.getClass.getSimpleName.replace("$","").equalsIgnoreCase(c) =>  spark.read.json(rddOfJsonStrings).as[Bar]
    case _ => throw ClassUnknownException //custom Exception
}
vdzxcuhz

vdzxcuhz4#

如何基于字符串调用df.as[]语句(如果可能的话)?
它不是(或者基于任何运行时值)。您可能会注意到,所有答案仍然需要:
有一个单独的分支机构 Foo 以及 Bar (并且为您要添加的每个类再添加一个分支);
在分支中重复类名两次。
您可以避免第二种情况:

import scala.reflect.{classTag, ClassTag}

val df: DataFrame = spark.read.json(rddOfJsonStrings)
// local function defined where df and classSelector are visible
def dfAsOption[T : Encoder : ClassTag] =
  Option.when(classSelector == classTag[T].runtimeClass.simpleName)(df.as[T])

dfAsOption[Foo].dfAsOption(asOption[Bar]).getOrElse(throw ClassUnknownException)

但首先,如果可能的话,你需要一个宏。我猜不是。

相关问题