我有一个自定义类型,它是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读取),包括String
,int
,double
- 因此我需要继续使用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)));
答案 0 :(得分:1)
TL; DR AvroCoder
只能与具体类一起使用。
AvroCoder
本质上使用Avro,这是一种基于模式的序列化格式,而不是一种序列化任意不透明Java对象的方法。
AvroCoder
使用给定类的字段作为模式 - 这些是在对数据进行编码时将被序列化的字段,以及在解码数据时进行反序列化的字段。您正在指定Object.class
,其中没有字段。
同样,字段将在指定类的新实例上设置。因此,在您的情况下,反序列化会创建一个新的Object
,并且由于Object
类没有设置任何字段,因此反序列化不会尝试在此{{1}上设置任何字段},最终得到一个基本的空Object
实例。
对于序列化/反序列化任意对象(尽管它们必须实现Object
),请使用Serializable
。