在以下代码中,我创建了一个Dataset<Person>
,并希望将其写到Avro文件中。由于使用ZonedDateTime
的Person类,Spark 2.1.0不会使用Encoders.bean(Person.class)
接受我(即NullPointerExceptions),所以我改用Encoders.kryo(Person.class)
。
调用ds.printSchema()
时,我看到数据集包含一个带有我的编码Person对象的字段。
调用ds.write()
时,我期望反序列化可以免费使用,并且我会看到Avro模式包含Person字段name
和lastUpdated
。不幸的是,它只是一个二进制字段。
public class Person
{
private String name;
private ZonedDateTime lastUpdated;
// constructor + getters/setters omitted
}
public class MyTest
{
private SparkContext sc;
@Before
public void setUp()
{
sc = new SparkContext(new SparkConf()
.setMaster("local[2]")
.setAppName("test"));
}
@Test
public void test()
{
final Person bob = new Person("Bob", ZonedDateTime.now());
Dataset<Person> ds = SparkSession.builder().sparkContext(sc).getOrCreate().sqlContext().createDataset(Arrays.asList(bob), Encoders.kryo(Person.class));
System.out.println(ds.first());
// com.db.rca.ts.fd.spark.Person@20d87335[name=Bob,lastUpdated=2018-10-01T19:23:18.742null[Europe/London]]
ds.printSchema();
// root
// |-- value: binary (nullable = true)
ds.write()
.mode(SaveMode.Overwrite)
.format("com.databricks.spark.avro")
.save("./target/output");
// avro file output contains the one binary field?
}
}
我已从示例中删除了业务逻辑以提供工作代码。将数据加载到类型安全的数据集中然后写出以使Person类的所有字段在Avro模式中可见的正确方法是什么?
如果JavaRDD
API尚不先进,我将恢复使用Dataset
API。