在spark批处理作业中,我通常将JSON数据源写入文件,并且可以使用DataFrame阅读器的损坏列功能在单独的位置写出损坏的数据,而另一个阅读器从同一位置写出有效数据工作。 (数据写为实木复合地板)
但是在Spark结构流中,我首先通过kafka以字符串形式读取流,然后使用from_json获取我的DataFrame。然后from_json使用JsonToStructs,它在解析器中使用FailFast模式,并且不将未解析的字符串返回到DataFrame中的列。 (请参阅参考资料中的“注意”)然后如何使用SSS将与我的架构和可能无效的JSON不匹配的损坏数据写入另一个位置?
最后,在批处理作业中,同一作业可以写入两个数据帧。但是Spark结构化流媒体需要对多个接收器进行特殊处理。然后在Spark 2.3.1(我的当前版本)中,应包括有关如何正确写入损坏的流和无效的流的详细信息...
参考:https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-Expression-JsonToStructs.html
val rawKafkaDataFrame=spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", config.broker)
.option("kafka.ssl.truststore.location", path.toString)
.option("kafka.ssl.truststore.password", config.pass)
.option("kafka.ssl.truststore.type", "JKS")
.option("kafka.security.protocol", "SSL")
.option("subscribe", config.topic)
.option("startingOffsets", "earliest")
.load()
val jsonDataFrame = rawKafkaDataFrame.select(col("value").cast("string"))
// does not provide a corrupt column or way to work with corrupt
jsonDataFrame.select(from_json(col("value"), schema)).select("jsontostructs(value).*")
答案 0 :(得分:0)
当您从字符串转换为json时,如果无法使用提供的架构进行解析,则它将返回null。您可以过滤空值并选择字符串。像这样的东西。
val jsonDF = jsonDataFrame.withColumn("json", from_json(col("value"), schema))
val invalidJsonDF = jsonDF.filter(col("json").isNull).select("value")
答案 1 :(得分:0)
我只是想找出结构化流的_corrupt_record等效项。这是我想出的;希望它可以使您更接近所要寻找的东西:
// add a status column to partition our output by
// optional: only keep the unparsed json if it was corrupt
// writes up to 2 subdirs: 'out.par/status=OK' and 'out.par/status=CORRUPT'
// additional status codes for validation of nested fields could be added in similar fashion
df.withColumn("struct", from_json($"value", schema))
.withColumn("status", when($"struct".isNull, lit("CORRUPT")).otherwise(lit("OK")))
.withColumn("value", when($"status" <=> lit("CORRUPT"), $"value"))
.write
.partitionBy("status")
.parquet("out.par")