所以我有一个数据框架,我从我的数据库中的表收集。当我从数据库中读取它时,json列成为我的数据框架中的字符串,没有问题,我使用:
转换它df_json = spark.read.json(df.rdd.map(lambda r: r.JsonCol))
df = df.withColumn("json_data", from_json("JsonCol", df_json.schema)).drop("JsonCol")
现在我得到了我的数据框架的以下模式,我已经删除了很多不相关的属性从json,但相信我有很多:
root
|-- Id: integer (nullable = true)
|-- json_data: struct (nullable = false)
| |-- object: struct (nullable = true)
| | |-- Id: long (nullable = true)
| | |-- Id: string (nullable = true)
| | |-- ... many more properties
这里有问题,在嵌套对象对象中,我有两个具有相同名称的属性。这是因为数据库中的一些旧条目将对象的Id作为字符串类型,但后来将其更改为长类型。因此,我不能使用:
来编写我的数据框架df.write.format("delta").option('mergeSchema', 'true').option("inferSchema", "true").option("overwriteSchema", "true").mode("overwrite").save(output_folder)
我得到以下错误:
AnalysisException: Found duplicate column(s) in the metadata update: json.object.id;
我该如何解决这个问题?理想情况下,我想合并这两个列名,通过将Id与字符串类型转换为长类型并合并它们。我可以得到这样一个模式:
root
|-- Id: integer (nullable = true)
|-- json_data: struct (nullable = false)
| |-- object: struct (nullable = true)
| | |-- Id: long (nullable = true)
| | |-- ... many more properties
注意json的根也有一个名为Id的属性,我希望它不受影响!
有人能帮我一下吗?使用:
df = df.withColumn("json_data", from_json("JsonCol", df_json.schema)).drop("JsonCol")
我使用了一个解决方案,我在JsonCol上预先使用了正则表达式替换:
df = df.withColumn("JsonCol", regexp_replace(col("JsonCol"), r'"Id":"[0-9]+"', '"Id":[0-9]+'))
删除"在Id的每一边,这意味着它们将被解释为长而不是字符串。
把它们放在一起:
df = df.withColumn("JsonCol", regexp_replace(col("JsonCol"), r'"Id":"[0-9]+"', '"Id":[0-9]+'))
df_json = spark.read.json(df.rdd.map(lambda r: r.JsonCol))
df = df.withColumn("json_data", from_json("JsonCol", df_json.schema)).drop("JsonCol")
这给了我预期的输出,之后我可以正确地保存它:
root
|-- Id: integer (nullable = true)
|-- json_data: struct (nullable = false)
| |-- object: struct (nullable = true)
| | |-- Id: long (nullable = true)