【问题标题】:Dataflow AvroCoder seems to lose type information for Object serializationDataflow AvroCoder 似乎丢失了对象序列化的类型信息
【发布时间】:2016-12-12 03:46:08
【问题描述】:

我有一个自定义类型,它通过PCollections 传递并用@DefaultCoder(AvroCoder.class) 进行注释 - 此类型包含一些原语以及使用阅读器从JSON 字符串中提取的Map<String, Object>

最初读取时,来自 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)));

【问题讨论】:

    标签: avro google-cloud-dataflow


    【解决方案1】:

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

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

    AvroCoder 使用给定类的字段作为模式 - 这些字段将在编码数据时序列化并在解码时反序列化。您正在指定 Object.class,它没有字段。

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

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

    【讨论】:

    • 除了实现Serializable,我几乎都这样做了,我使用一个成员变量来存储序列化的byte[],这很难看,因为我们有SerializableCoder。将更新它 - 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 2018-07-13
    • 2019-04-13
    • 2016-09-28
    • 1970-01-01
    相关资源
    最近更新 更多