【发布时间】:2021-03-10 09:56:43
【问题描述】:
使用 Spark 2.3.2。
我正在尝试使用 DataFrame 的某些列的值并将它们放入现有的 JSON 结构中。假设我有这个 DataFrame:
val testDF = Seq(("""{"foo": "bar", "meta":{"app1":{"p":"2", "o":"100"}, "app2":{"p":"5", "o":"200"}}}""", "10", "1337")).toDF("key", "p", "o")
// used as key for nested json structure
val app = "appX"
基本上,我想从这个专栏中得到
{
"foo": "bar",
"meta": {
"app1": {
"p": "2",
"o": "100"
},
"app2": {
"p": "5",
"o": "200"
}
}
}
到这里:
{
"meta": {
"app1": {
"p": "2",
"o": "100"
},
"app2": {
"p": "5",
"o": "200"
},
"appX": {
"p": "10",
"o": "1337"
}
}
}
基于 DataFrame 的 p 和 o 列。
我试过了:
def process(inputDF: DataFrame, appName: String): DataFrame = {
val res = inputDF
.withColumn(appName, to_json(expr("(p, o)")))
.withColumn("meta", struct(get_json_object('key, "$.meta")))
.selectExpr(s"""struct(meta.*, ${appName} as ${appName}) as myStruct""")
.select(to_json('myStruct).as("newMeta"))
res.show(false)
res
}
val resultDF = process(testDF, app)
val resultString = resultDF.select("newMeta").collectAsList().get(0).getString(0)
StringContext.treatEscapes(resultString) must be ("""{"meta":{"app1":{"p":"2","o":"100"},"app2":{"p":"5","o":"200"},"appX":{"p":"10","o":"1337"}}}""")
但是这个断言不匹配,因为我不能
- 将
appX的内容获取到其他两个应用的相同级别 - 不知道如何正确处理引号,并且
- 不知道如何将“col1”重命名为“meta”。
测试失败:
Expected :"{"[meta":{"app1":{"p":"2","o":"100"},"app2":{"p":"5","o":"200"},"appX":{"p":"10","o":"1337"}}]}"
Actual :"{"[col1":"{"app1":{"p":"2","o":"100"},"app2":{"p":"5","o":"200"}}","appX":"{"p":"10","o":"1337"}"]}"
【问题讨论】:
-
是2.3.2,添加到问题中
-
这一行
.withColumn("meta", struct(get_json_object('key, "$.meta")))是错误的,它不会展平meta列值。
标签: json apache-spark apache-spark-sql