Spark非常擅长将JSON解析为磁盘上的初始读取中的嵌套StructType
,但是如果我已经在String
中有一个包含JSON的Dataset
列了,我想要要将其映射到带有Dataset
列的StructType
列中,并使用模式推断将整个数据集都考虑在内,同时充分利用并行状态并避免减少操作?
我知道函数schema_of_json
和from_json
,显然打算一起使用以完成此任务或类似的操作,但是我很难找到实际的工作代码示例,尤其是在Java中
我将接受任何提供Java示例并满足完整模式推断和完全非简化并行操作的目标的答案。或者,如果不可能的话,请采用最接近的解决方法。
我当前正在使用Spark 2.4.0。
我研究了以下相关问题:
Implicit schema discovery on a JSON-formatted Spark DataFrame column
这个问题类似于我的,尽管对于Scala而言。没有可接受的答案。 OP在评论中宣布,他们找到了使from_schema
正常工作的“骇客”解决方案。解决方案的问题在于,除了“ hackiness”之外,它还只能从数据帧的第一行推断模式,因此类型可能过于严格:
val jsonSchema: String = df.select(schema_of_json(df.select(col("custom")).first.getString(0))).as[String].first
编辑:我尝试了以下注释中讨论的指示here的解决方案。这是实现:
SparkSession spark = SparkSession
.builder()
.appName("example")
.master("local[*]")
.getOrCreate();
Dataset<Row> df = spark.read().text(conf.getSourcePath());
df.cache();
String schema = df.select(schema_of_json(col("value")))
.as(Encoders.STRING())
.first();
df.withColumn("parsedJson", from_json(col("value"), schema, new HashMap<String, String>()))
.drop("value")
.write()
.mode("append")
.parquet(conf.getDestinationPath());
从这段代码中我得到了一个错误:
AnalysisException: cannot resolve 'schemaofjson(`value`)' due to data type mismatch: The input json should be a string literal and not null; however, got `value`.;;
'Project [schemaofjson(value#0) AS schemaOfjson(value)#20]
+- Relation[value#0] text
此错误将我引向以下Spark Pull请求: https://github.com/apache/spark/pull/22775
似乎表明schema_of_json
从未打算应用于整个表以对整个事物进行模式推断,而是从直接使用传入的单个文字JSON样本推断模式lit("some json")
。在那种情况下,我不知道Spark为从整个表上的JSON进行完整模式推断提供任何解决方案。除非这里的某人可以更正我对此请求请求的阅读或提供其他方法?
答案 0 :(得分:0)
使用DataFrameReader.json(Dataset<String>)
实际上有一个非常简单的解决方案,不知道为什么它没有出现在我的搜索中:
Dataset<String> ds = ...;
spark.read()
.json(ds)
.write()
.mode("append")
.parquet(conf.getDestinationPath());
如果源数据集中有多个列,显然您可以只选择要操作的一列。内容类型必须为String
(例如,不能为Row
)。