Извлечение json данных из StringType Spark. SQL - PullRequest
1 голос
/ 25 марта 2020

Существует таблица улья с одним столбцом типа string.

hive> desc logical_control.test1;
OK
test_field_1          string                  test field 1
val df2 = spark.sql("select * from logical_control.test1")

df2.printSchema()
root
|-- test_field_1: string (nullable = true)
df2.show(false)
+------------------------+
|test_field_1            |
+------------------------+
|[[str0], [str1], [str2]]|
+------------------------+

Как преобразовать его в структурированный столбец, как показано ниже?

root
|-- A: array (nullable = true)
|    |-- element: struct (containsNull = true)
|    |    |-- S: string (nullable = true)

Я пытался восстановить его с исходной схемой, в которой данные структурировались до того, как были записаны в hdfs. Но json_data имеет значение null.

val schema = StructType(
    Seq(
      StructField("A", ArrayType(
        StructType(
          Seq(
            StructField("S", StringType, nullable = true))
        )
      ), nullable = true)
    )
  )

val df3 = df2.withColumn("json_data", from_json(col("test_field_1"), schema))

df3.printSchema()
root
|-- test_field_1: string (nullable = true)
|-- json_data: struct (nullable = true)
|    |-- A: array (nullable = true)
|    |    |-- element: struct (containsNull = true)
|    |    |    |-- S: string (nullable = true)
df3.show(false)
+------------------------+---------+
|test_field_1            |json_data|
+------------------------+---------+
|[[str0], [str1], [str2]]|null     |
+------------------------+---------+

1 Ответ

1 голос
/ 25 марта 2020

Если структура test_field_1 фиксирована, и вы не против "разбора" поля самостоятельно, вы можете использовать udf для выполнения преобразования:

case class S(S:String)
def toArray: String => Array[S] = _.replaceAll("[\\[\\]]","").split(",").map(s => S(s.trim))
val toArrayUdf = udf(toArray)

val df3 = df2.withColumn("json_data", toArrayUdf(col("test_field_1")))
df3.printSchema()
df3.show(false)

печатает

root
 |-- test_field_1: string (nullable = true)
 |-- json_data: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- S: string (nullable = true)

+------------------------+------------------------+
|test_field_1            |json_data               |
+------------------------+------------------------+
|[[str0], [str1], [str2]]|[[str0], [str1], [str2]]|
+------------------------+------------------------+

Сложная задача - создать второй уровень (element: struct) структуры. Я использовал класс case S для создания этой структуры.

...