数据流AvroCoder似乎丢失了对象序列化

时间:2016-12-12 03:46:08

标签: avro google-cloud-dataflow

我有一个自定义类型,它是PCollections传递的,并注明了@DefaultCoder(AvroCoder.class) - 这个类型包含一些基元以及一个Map<String, Object>,它是使用一个JSON字符串提取的读者。

最初读取时,会保留JSON中的类型信息,因此,我可以将值转换为String或任何其他类型(如果适用)。但是在管道的后期阶段,当我将相同的值转换为String时,我得到一个像java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String这样的异常 - 这可能意味着Map中每个对象的类型信息都有没有在管道中传递。这是AvroCoder的限制 - 如果是这样,是否有解决方法或我做错了什么? Map值将具有不同类型(从JSON读取),包括Stringintdouble - 因此我需要继续使用Object类型。

为了验证编码器的行为,我构建了一个模拟行为的示例程序,最终会得到ClassCastException,如上所述。

    String filename = "out.avro";
    AvroCoder<Object> coder = AvroCoder.of(TypeDescriptor.of(Object.class));
    FileOutputStream fos = new FileOutputStream(filename);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    coder.encode("test", oos, new Coder.Context(true));
    oos.close();
    fos.close();

    FileInputStream fis = new FileInputStream(filename);
    ObjectInputStream ois = new ObjectInputStream(fis);
    System.out.println((String) coder.decode(ois, new Coder.Context(true)));

1 个答案:

答案 0 :(得分:1)

TL; DR AvroCoder只能与具体类一起使用。

AvroCoder本质上使用Avro,这是一种基于模式的序列化格式,而不是一种序列化任意不透明Java对象的方法。

AvroCoder使用给定类的字段作为模式 - 这些是在对数据进行编码时将被序列化的字段,以及在解码数据时进行反序列化的字段。您正在指定Object.class,其中没有字段。

同样,字段将在指定类的新实例上设置。因此,在您的情况下,反序列化会创建一个新的Object,并且由于Object类没有设置任何字段,因此反序列化不会尝试在此{{1}上设置任何字段},最终得到一个基本的空Object实例。

对于序列化/反序列化任意对象(尽管它们必须实现Object),请使用Serializable