Преобразовать выражение String в фактическое выражение рабочего экземпляра - PullRequest
2 голосов
/ 16 июня 2019

Я пытаюсь преобразовать выражение в 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 ]

3 голосов
/ 16 июня 2019

Ваш код в квазицитатах должен иметь правильный синтаксис Scala, поэтому вам нужно указывать кавычки для строк.Вы также должны были бы обеспечить весь необходимый импорт.Это работает:

val toolbox = currentMirror.mkToolBox()
  val code1 =
    q"""
       //we need to import all sql types
       import org.apache.spark.sql.types._
       StructType(
           //StructType needs list
           List(
             //name arguments need to be in proper quotes
             StructField("id",IntegerType,true), 
             StructField("name",StringType,true),
             StructField("tstamp",TimestampType,true),
             StructField("date",DateType,true)
           )
       )
      """
val sType = toolbox.compile(code1)().asInstanceOf[StructType]

println(sType)

Но, возможно, вместо того, чтобы пытаться перекомпилировать код, вы должны рассмотреть другие альтернативы как сериализацию типа структуры (возможно, в JSON?).

3 голосов
/ 16 июня 2019

Если 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

Код взят из org.apache.spark.sql.types.StructType объекта-компаньона от Spark. Вы не можете использовать его напрямую, так как он находится в закрытом пакете. Более того, он использует LegacyTypeStringParser, поэтому я не уверен, достаточно ли это для производственного кода.

...