将字符串表达式转换为实际的工作实例表达式

时间:2019-06-16 11:48:25

标签: string scala apache-spark expression scala-quasiquotes

我正在尝试将Scala中的表达式转换为工作代码,该表达式将作为String保存在数据库中。

我尝试了Reflect Toolbox,Groovy等。但是我似乎无法实现我所需要的。

这是我尝试过的:


import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox

val toolbox = currentMirror.mkToolBox()
val code1 = q"""StructType(StructField(id,IntegerType,true), StructField(name,StringType,true), StructField(tstamp,TimestampType,true), StructField(date,DateType,true))"""
val sType = toolbox.compile(code1)().asInstanceOf[StructType]

我需要使用 sType 实例将customSchema传递到csv文件以创建数据帧,但似乎失败。

有什么方法可以获取StructType的字符串表达式以转换为实际的StructType实例吗?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

如果StructType来自Spark,而您只想将String转换为StructType,则不需要反射。您可以尝试以下方法:

import org.apache.spark.sql.catalyst.parser.LegacyTypeStringParser
import org.apache.spark.sql.types.{DataType, StructType}

import scala.util.Try

def fromString(raw: String): StructType =
  Try(DataType.fromJson(raw)).getOrElse(LegacyTypeStringParser.parse(raw)) match {
    case t: StructType => t
    case _             => throw new RuntimeException(s"Failed parsing: $raw")
  }

val code1 =
  """StructType(Array(StructField(id,IntegerType,true), StructField(name,StringType,true), StructField(tstamp,TimestampType,true), StructField(date,DateType,true)))"""
fromString(code1) // res0: org.apache.spark.sql.types.StructType

代码取自Spark中的org.apache.spark.sql.types.StructType伴随对象。您不能直接使用它,因为它在私人包装中。而且,它使用LegacyTypeStringParser,所以我不确定这对生产代码是否足够。

答案 1 :(得分:3)

您在准引号内的代码必须是有效的Scala语法,因此您需要为字符串提供引号。您还需要提供所有必要的导入。这有效:

fileprivate func fetchData() {

   if self.movieDays != nil
   {
      self.movieDays.removeAll() 
      self.headerMovies.removeAll()
   }

   let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    Service.shared.fetchMoviesBySchedule { (movieDays, err) in
        if let err = err    {
            print("Failed to fetch movies", err)
            return
        }
        self.movieDays = movieDays?.data
        dispatchGroup.leave()
    }

    dispatchGroup.enter()
    Service.shared.fetchFeaturedMovies { (movies, err) in
        if let err = err    {
            print("Failed to fetch featured movies", err)
            return
        }
        self.headerMovies = movies?.data ?? []
        dispatchGroup.leave()
    }

    dispatchGroup.notify(queue: .main) {
        print("complete dispatch")
        self.collectionView.reloadData()
        self.collectionView.refreshControl?.endRefreshing()
    }
}

但是也许不是尝试重新编译代码,而是应考虑以其他方式将结构类型序列化(也许是JSON?)。