用于解析 JSON 架构文件的 SQL DDL



是否可以将SQL DDL语句解析为简单的JSON模式文件,如下所示,而无需使用任何工具,仅使用Scala/Python/shell脚本?

CREATE TABLE TEMP (
      ID INT,
      NAME STRING)
[
  {
    "tableName": "temp",
    "columns": [
      {
        "columnname": "id",
        "datatype": "int"
      },
      {
        "columnname": "name",
        "datatype": "string"
      }
    ]
  }
]

您可以使用以下逻辑(Scala 代码(从 DDL 创建 JSON 形式的字符串。一旦字符串被制作出来,它就会被转换成一个Dataframe。然后将此Dataframe作为 JSON 文件保存到 HDFS/Amazon S3 中,使用名为 write.json 的内置 API Dataframe's

import org.apache.spark.sql.types._
import spark.implicits._
val createSql = "CREATE TABLE TEMP (ID INT, NAME STRING)"
var jsonString = """[{"tableName":"""" + createSql.split(" ")(2).toLowerCase + ""," + ""columns":["
createSql.split(s"\(")(1).split(s"\)")(0).split(",").map(r => {
jsonString += "{" + ""columnname": " + """ + r.trim.split(" ")(0).toLowerCase + ""," + ""datatype": " + """ + r.trim.split(" ")(1).toLowerCase + ""},"
})
jsonString = jsonString.patch(jsonString.lastIndexOf(','), "", 1) + "]}]"
val schema: StructType = null
val reader = spark.read
Option(schema).foreach(reader.schema)
val df = reader.json(sc.parallelize(Array(jsonString)))
df.coalesce(1).write.json("<targetlocation>")

如果您有任何问题,请告诉我。

有一些匹配,例如这里描述的:如何在 Scala 中使用正则表达式进行模式匹配? 假设您的初始表达式是作为行序列传入的,则此代码可能如下所示(请注意,下面使用的 JSONObject 已被弃用,因此请将其替换为一些替代方法(。

object Parser {
    implicit class Regex(sc: StringContext) {
      def r = new util.matching.Regex(sc.parts.mkString, sc.parts.tail.map(_ => "x"): _*)
    }
    def toJson(tablename: String, columns: Seq[(String,String)]): String = {
      val columnList: List[JSONObject] = columns.toStream.map(x => JSONObject(Map("columnname" -> x._1, "datatype" -> x._2))).toList
      JSONArray(List(JSONObject(Map("tableName" -> tablename, "columns" -> JSONArray(columnList))))).toString()
    }
    def parse(lines: Seq[String]): (String, Seq[(String,String)]) = {
      lines.mkString("").toLowerCase match {
        case r"creates+tables+(S+)${tablename}s+((.+)${columns}).*" =>
          val columnWithType: immutable.Seq[(String, String)] = columns.split(",").toStream
            .map(x => x.split("\s+"))
            .map(x => (x.head.toLowerCase, x(1).toLowerCase))
          (tablename, columnWithType)
        case _ => ("",Seq.empty)
      }
    }
  }

要使用测试字符串进行测试,请执行以下操作:

val data: (String, Seq[(String, String)]) = Parser.parse(Seq("CREATE TABLE TEMP (", "ID INT,", "NAME STRING)"))
      println(Parser.toJson(data._1, data._2))

使用 scala.util.parsing.combinator 包,你可以像这样用 DDL 定义你的 Lexer 和 Grammer 解析器,

import scala.util.parsing.combinator._
class JSON extends JavaTokenParsers {
  def value: Parser[Any] = obj | arr | stringLiteral | floatingPointNumber | "null" | "true" | "false"
  def obj: Parser[Any] = "{"~repsep(member, ",")~"}"
  def arr: Parser[Any] = "["~repsep(value, ",")~"]"
  def member: Parser[Any] = stringLiteral~":"~value
} 

上面的代码将用于将 JSON 字符串解析为 lexel 流以供进一步处理。阅读文档,您将能够定义 SQL DDL 解析器。

我们刚刚在 https://github.com/deepstartup/jsonutils 年发布了这个包。也许你会发现它很有用。如果您需要我们更新某些内容,请打开 JIRA。

尝试:

    pip install DDLJ
    from DDLj import genddl
    genddl(*param1,param2,*param3,*param4)
Where
param1= JSON Schema File
param2=Database (Default Oracle)
Param3= Glossary file
Param4= DDL output script

最新更新