如何将DataSet <row>转换为JSON消息的DataSet以写入Kafka?

时间:2017-05-31 09:06:45

标签: java apache-spark apache-kafka apache-spark-sql spark-structured-streaming

我使用Spark 2.1.1。

我有以下DataSet<Row> ds1;

 name   | ratio | count  // column names
"hello" |  1.56 | 34 

ds1.isStreaming给出true

我正在尝试生成DataSet<String> ds2。换句话说,当我写一个卡夫卡水槽时,我想写这样的东西

{"name": "hello", "ratio": 1.56, "count": 34}

我尝试了类似df2.toJSON().writeStream().foreach(new KafkaSink()).start()之类的内容,但后来又出现了以下错误

Queries with streaming sources must be executed with writeStream.start()

to_jsonjson_tuple但是我不确定如何在这里利用它们?

我使用json_tuple()函数

尝试了以下操作
 Dataset<String> df4 = df3.select(json_tuple(new Column("result"), " name", "ratio", "count")).as(Encoders.STRING());

我收到以下错误:

  

无法解析给定输入列的“result”:[名称,比率,计数] ;;

1 个答案:

答案 0 :(得分:3)

tl; dr 使用struct函数后跟to_json(由于toJSON由于SPARK-17029已修复而导致流式数据集已被中断20 days ago)。

引用struct的scaladoc:

  

struct(colName:String,colNames:String *):Column 创建一个组成多个输入列的新struct列。

鉴于您使用Java API,您还有4种不同的struct函数变体:

  

public static Column struct(Column ... cols)创建一个新的struct列。

使用to_json功能可以涵盖您的案例:

  

public static Column to_json(E列)将包含StructType的列转换为具有指定架构的JSON字符串。

以下是Scala代码(将其转换为Java是您的主要练习):

val ds1 = Seq(("hello", 1.56, 34)).toDF("name", "ratio", "count")
val recordCol = to_json(struct("name", "ratio", "count")) as "record"
scala> ds1.select(recordCol).show(truncate = false)
+----------------------------------------+
|record                                  |
+----------------------------------------+
|{"name":"hello","ratio":1.56,"count":34}|
+----------------------------------------+

我也尝试过你的解决方案(今天使用Spark 2.3.0-SNAPSHOT),看起来效果很好。

val fromKafka = spark.
  readStream.
  format("kafka").
  option("subscribe", "topic1").
  option("kafka.bootstrap.servers", "localhost:9092").
  load.
  select('value cast "string")
fromKafka.
  toJSON. // <-- JSON conversion
  writeStream.
  format("console"). // using console sink
  start
SPARK-19719中添加了{p> format("kafka"),但在2.1.0中未提供。