我需要将数据帧的UUID列转换为具有相同十六进制序列的String列,例如。如果特定字段具有以下值:
JUUID("940bf38c-92d7-49fd-8ad0-67627c6b5084")
应该转换列,使其输出为
"940bf38c-92d7-49fd-8ad0-67627c6b5084"
我打印出架构,发现该列以结构形式出现:
|-- resourceId: struct (nullable = true)
| |-- subType: byte (nullable = false)
| |-- data: binary (nullable = true)
这就是为什么如果我将UDF定义为接受String的输入,则永远不会调用它。我应该如何解决这个问题?
抱歉,昨天我没有时间发布代码段。此后,我有所进步,现在我要发表我的发现。
我最初使用RDD加载Mongo文档:
JavaMongoRDD<Document> rdd = MongoSpark.load(sc);
将第一个文档加载为JSON:
System.out.println(rdd.first().toJson());
输出如下:
"relativeId": {"$binary": "KUrqX+N+IP663myObpnOhA==", "$type": "03"}
从this question here,我获得了如何将二进制转换回十六进制格式。
现在我需要做的是将内联二进制文件更改为JSON中正确的十六进制格式,并将其写回。我花了一段时间查看数据集的方式,看看是否可以使用UDF:
Dataset<Row> ds = rdd.toDF();
spark.sqlContext().udf().registerJava("UUIDTransformer", UUIDTransformer.class.getName(),
DataTypes.StringType);
ds = ds.withColumn("resourceId2", functions.callUDF("UUIDTransformer", functions.col("resourceId")));
UDF如下:
public class UUIDTransformer implements UDF1<GenericRowWithSchema, String> {
// @SuppressWarnings("deprecation")
public String call(GenericRowWithSchema columnValue) throws Exception {
System.out.println("Value of col: " + columnValue.toString());
return "Successful";
}
}
正在打印值,但是它们与我将它们作为来自RDD的JSON时获得的二进制值不同,并且它们也不能转换回十六进制,因为它们给出了它们不正确的例外十六进制代码。所以我又回到了RDD。
但是现在的问题是,我如何将内联的更改应用于每个这样的JUUID列,有时它们也嵌套在结构中?
为了进行内联转换,这就是我所做的:
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
使用我在OP中提到的链接中找到的UUID解码和编码程序,然后继续使用此代码替换现有的UUID列:
jsonObject.addProperty("resourceId", UUIDDecodeEncode
.decompress(jsonObject.get("resourceId").getAsJsonObject().get("$binary").getAsString()).toString());
resourceID列在原始JSON中如下显示,我必须从中取出编码部分:
"resourceId":{"$binary":"vEOsgXxlT7oX5rKoOAGRrA==","$type":"03"}