Поток данных AvroCoder, похоже, теряет информацию о типе для сериализации объектов
У меня есть пользовательский тип, который передается 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)));
1 ответ
TL;DR AvroCoder
может использоваться только с конкретным классом.
AvroCoder
по своей природе использует Avro, который является форматом сериализации на основе схемы, а не способом сериализации произвольных непрозрачных объектов Java.
AvroCoder
использует в качестве схемы поля данного класса - эти поля будут сериализованы при кодировании данных и десериализации при их декодировании. Вы указываете Object.class
, который не имеет полей.
Аналогично, поля будут установлены для нового экземпляра указанного класса. Так что в вашем случае десериализация создает новый Object
и так как Object
класс не устанавливает никаких полей, десериализация не пытается установить какие-либо поля в этом Object
, и вы в конечном итоге с основным пустым Object
пример.
Для сериализации / десериализации произвольных объектов (хотя они должны реализовать Serializable
), используйте SerializableCoder
,