#json #apache-spark
#json #apache-spark
Вопрос:
У меня есть Spark DataFrame
со следующими столбцами
uuid|some_data
"A" |"ABC"
"B" |"DEF"
Мне нужно преобразовать это во вложенный JSON следующего формата,
{"data":[{"attributes":[{"uuid":"A","some_data":"ABC"}]}]}
{"data":[{"attributes":[{"uuid":"B","some_data":"DEF"}]}]}
Я попробовал приведенный ниже код для достижения этой цели,
val jsonDF= dataFrame.select(
to_json(struct(dataFrame.columns.map(column):_*)).alias("attributes")
)
val jsonDF2= jsonDF.select(
to_json(struct(jsonDF(column):_*)).alias("data")
)
val jsonDF3= jsonDF2(
to_json(struct(jsonDF2.columns.map(column):_*)).alias("value")
).selectExpr("CAST(value as STRING)")
В итоге был получен следующий формат,
{"data": {"attributes": {"uuid":"A","some_data":"ABC}}}
{"data": {"attributes": {"uuid":"B","some_data":"DEF}}}
Пожалуйста, дайте мне знать, какие изменения мне нужно внести, чтобы привести его к требуемому формату.
Ответ №1:
Для каждого документа JSON требуется свой собственный struct
. Дополнительно вам понадобится array
для обертывания data
и еще один для обертывания attributes
:
import org.apache.spark.sql.functions.{array, struct}
val jsonData = struct( // Outermost JSON document
array( // Data field as an array
struct( // Intermediate JSON document with attributes field
array( // Innermost array
struct( // Innermost JSON document
$"uuid", // Payload, you can use df.columns.map(col):_* instead
$"some_data"
)
) as "attributes" // Alias for innermost array field
)
) as "data") // Alias for array field
Комбинированный:
Seq(("A", "ABC"))
.toDF("uuid", "some_data")
.select(to_json(jsonData) as "data")
.show(false)
----------------------------------------------------------
|data |
----------------------------------------------------------
|{"data":[{"attributes":[{"uuid":"A","some_data":"ABC"}]}]}|
----------------------------------------------------------