是否有一种简单的方法可以将包含JSON的JavaRDD <String>转换为自定义Java对象

时间:2019-06-17 06:00:06

标签: java json string apache-spark rdd

我有一个火花流上下文,可以从Kafka Consumer获取数据流。数据包含JSON对象。我需要将其转换为自定义Java对象,以便进行一些处理。有没有简单的方法可以做到这一点?基本上,我想要一种将JavaRDD转换为普通字符串的方法,以便可以使用gson.fromJSON将其转换为简单的POJO类对象。

我尝试了一些方法,但是遇到了Serilaization问题

JavaDStream jds = stream.map(x-> x.value());

    jds.foreachRDD(x -> System.out.println(x.count()));

    jds.foreachRDD(new VoidFunction<JavaRDD<String>>() {

        private static final long serialVersionUID = 1L;

        @Override
        public void call(JavaRDD<String> rdd) {
            rdd.foreach(a -> {
                TransactionData tr = gson.fromJson(a, TransactionData.class);
            }
            );
        }

TransactionData是一个普通的Java bean类,具有两个字段id和amount以及它们的getter / setter方法

在上面的代码中,我在序列化方面遇到错误。 这是错误: org.apache.spark.SparkException:任务无法序列化原因:java.io.NotSerializableException:com.google.gson.Gson序列化堆栈:-对象不可序列化(类:com.google.gson.Gson,值:{serializeNulls: falsefactories:[Factory [typeHierarchy = com.google.gson.JsonElement,adapter = com.google.gson.internal.bind.TypeAdapters $ 25 @ 35c645ea]。...

关于如何解决此问题的任何想法?

1 个答案:

答案 0 :(得分:0)

这里的问题是Gson不可序列化,可以通过避免Gson序列化并仅在处理期间创建实例来解决。可以创建Gson的包装器类,并在主代码中使用;在示例中使用Car类代替TransactionData:

public class CarConverter implements Serializable {
transient Gson gson;

private Gson getGson() {
    if (gson == null) {
        gson = new Gson();
    }
    return gson;
}

public JavaRDD<Car> convert(JavaRDD<String> rdd) {
    return rdd.map(a -> getGson().fromJson(a, Car.class));
}
}

用法示例:

    List<String> data = Lists.newArrayList("{\"brand\":\"Jeep\", \"doors\": 3}", "{\"brand\":\"Slavuta\", \"doors\": 4}");
    JavaRDD<String> rdd = jsc().parallelize(data);
    CarConverter converter = new CarConverter();
    JavaRDD<Car> result = converter.convert(rdd);