如何从二进制protobuf中提取JSON?

时间:2018-03-05 15:22:14

标签: scala apache-spark protocol-buffers spark-structured-streaming

将Apache Spark 2.2.0结构化流视为:

jsonStream.printSchema()
root
 |-- body: binary (nullable = true)

正文中的数据是Protocol Buffers v2类型和嵌套的JSON。它看起来像

syntax = "proto2";

message Data {
  required string data = 1;
}

message List {
  repeated Data entry = 1;
}

如何在Spark中提取数据以“进一步”处理它?<​​/ p>

我查看了ScalaPB,但是当我在Jupyter中运行我的代码时,无法将“.proto”代码包含在内联中。我也不知道如何将数据帧转换为流上的RDD。由于流媒体来源,尝试.rdd失败。

Update 1 :我想出了如何使用ScalaPB的控制台工具从protobuf规范生成Scala文件。我仍然无法导入它们,因为“类型不匹配”。

1 个答案:

答案 0 :(得分:2)

tl; dr 编写用户定义函数(UDF)以将二进制字段(带有JSON的protobuf)反序列化为JSON。

将序列化的bodybinary格式)视为表格列。暂时忘记结构化流(和流数据集)。

让我再将问题改为以下内容:

  

如何将二进制值转换(也称为转换为)[here-your-format]?

某些格式直接cast - 能够将二进制文件转换为字符串,如下所示:

$"body" cast "string"

如果字符串是JSON或unixtime,则可以使用内置的“转换器”,例如from_jsonfrom_unixtime {/ 3}}。

介绍应该会提示您如何进行像您这样的转换。

  

正文中的数据类型为Protocol Buffers v2和嵌套的JSON。

要处理这些字段(protobuf + json),你必须编写一个Scala函数来将“payload”解码为JSON并使用functions创建一个用户定义的函数(UDF):

  

udf(f:UDF1 [_,_],returnType:DataType):UserDefinedFunction 将Java UDF1实例定义为用户定义的函数(UDF)。调用者必须指定输出数据类型,并且没有自动输入类型强制。默认情况下,返回的UDF是确定性的。要将其更改为非确定性,请调用API UserDefinedFunction.asNondeterministic()

然后使用from_jsonget_json_object等功能。

为了简化您的情况,编写一个单参数函数来执行转换,并使用udf函数将其包装到UDF中。

  

尝试.rdd因流媒体源而失败。

使用udfDataset.foreach

  

foreach(f:(T)⇒单位):单位将函数f应用于所有行。

     

foreachPartition(f:(Iterator [T])⇒Unit):Unit 将函数f应用于此数据集的每个分区。