Поток данных 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,

Другие вопросы по тегам