Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Как десериализовать объекты более старой версии?


Автор: Barvetal 22.1.2009, 16:43
Всем добрый день!

У меня есть структура данных, которая используется в двух приложениях: в одном эта структура создаётся и правится, в другом читается.

Соответственно, в первом приложении я свой объект сохраняю в файл:

[SRC java]    public static void saveToFile(MyObject obj, String filePath) {
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        ObjectOutputStream out = null;
        try {
            try {
                fos = new FileOutputStream(filePath);
                bos = new BufferedOutputStream(fos);
                out = new ObjectOutputStream(bos);
                out.writeObject(obj);
            } finally {
                out.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }[/SRC]

Во втором приложении читаю объект аналогичным образом (через in.readObject();).

Всё вроде хорошо, но беспокоит следующее:
Допустим, я написал новую версию системы. В новой версии класс MyObject изменился (например, добавилось новое поле, изменился тип существующего или какое-то поле было удалено).

Как мне из новой версии программы открыть старую версию класса MyObject? Ведь определение то класса изменилось!!!

Автор: AndrewMormysh 22.1.2009, 17:40
Думаю достаточно будет подложить приложению-ридеру старый класс, чтобы он его использовал для десериализации объекта.

Автор: Temdegon 22.1.2009, 17:56
При попытке десериализации ты получаешь InvalidClassException? Или тебе именно нужно обеспечить совместимость как со старой версией класса так и с новой?

Автор: Barvetal 22.1.2009, 18:01
Цитата(Temdegon @ 22.1.2009,  17:56)
При попытке десериализации ты получаешь InvalidClassException? Или тебе именно нужно обеспечить совместимость как со старой версией класса так и с новой?

Нет, достаточно только чтобы новая версия приложения успешно разруливала старые классы и инициировала недостающие поля значениями по умолчанию

Автор: Temdegon 22.1.2009, 18:52
Я знаю, что есть такая штука: поменял что-то незначительное в классе (что никак не могло повлиять на сам процесс сериализации), и старые данные уже не читаются, т.к. для каждого сериализуемого класса на этапе компиляции определяется поле 
Код

private static final long serialVersionUID

и это поле сериализуется. код перед тем как десериализовать данные проверяет, совпадает ли это поле с полем класса. Если да, то делается десериализация, если нет - выкидывается эксепшн. Это ограничение можно обойти явно обьявив эту переменную в сериализуемом классе. Тогда все будет читаться всегда. Но этот метод не подходит для твоего случая, если ты хочешь менять типы полей, добавлять новые, т.е. делать что-то что явно повлияет на саму сериализацию. Даже если метод прокатит и данные десериализуются без исключения, маловероятно что это будет сделано правильно.

Добавлено через 4 минуты и 34 секунды
Возможно в твоем случае имеет смысл использовать Экстернализацию вместо сериализации (java.io.Externalizable). 

Автор: COVD 22.1.2009, 19:01
Возможно, для этого удобнее сериализовать в виде xml. Например, java.beans.XMLEncoder .. XMLDecoder . Если при десериализации обнаруживается , что сеттер отсутствует, то выдается сообщение и восстановление продолжается. Обьект должен быть бином. Инициировать новые поля надо самостоятельно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)