Страницы

Поиск по вопросам

Показаны сообщения с ярлыком десериализация. Показать все сообщения
Показаны сообщения с ярлыком десериализация. Показать все сообщения

вторник, 31 марта 2020 г.

Теряется ссылка на один и тот же объект при сериализации-десериализации через DataContract

#c_sharp #net #сериализация #десериализация


Пытаюсь сериализовать сложный объект через DataContract. Объект имеет список подобъектов,
которые имеют в свою очередь свой список (назовем - листья дерева). К этим листьям,
например, первого элемента списка основного объекта, можно добраться их других элементов
списка (ссылка одна и та же). Получается довольно сложный граф, в котором много связей.

При десериализации у каждого элемента списка - свои листья, т.е. ссылки теряются,
если в объекте источнике - это один и тот же лист, то после десериализации - просто копия.

Примерно так

    A                A
   / \              / \
  B   C    ====>   B   C
   \ /             |   |
    D              D   D[копия]


(это очень упрощенная схема)

Пробовал для всех классов прописать DataContract(IsReference = true), так, на всякий
случай - не помогло. 

Есть ли более "быстрый" способ корректной десериализации, кроме как "ручное" выстраивание
структуры повторяющей объект-источник?

Спасибо.
    


Ответы

Ответ 1



При создании сериализатора задайте ему настройку PreserveObjectReferences = true. var settings = new DataContractSerializerSettings { PreserveObjectReferences = true }; var dcs = new DataContractSerializer(typeof(SomeType), settings); Также можно использовать NetDataContractSerializer.

среда, 22 января 2020 г.

Вопрос по сериализации объектов в java

#java #исключения #наследование #сериализация #десериализация


Есть классы, расположенные в определённой иерархии наследования:

public class Program {
    public Program(){
        System.out.println("Текст");
    }
}

public class Wild extends Program{
    public Wild(){
        System.out.println("НеТекст");
    }
}

public class BasicProgramists extends Wild{
    public BasicProgramists(){
        System.out.println("Бесполезная программа");
    }
}

import java.io.*;

public class BasicUser extends BasicProgramists implements Serializable {
    public BasicUser(){
        System.out.println("Использование бесполезной программы");
    }

    public static void main(String[] args) {
        BasicUser user = new BasicUser();
        System.out.println();
        try {
            ObjectOutputStream or = new ObjectOutputStream(new FileOutputStream("Progg.ser"));
            or.writeObject(user);
            or.close();
        }
        catch (IOException ex){
            ex.printStackTrace();
        }

        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream("Progg.ser"));
            BasicUser user1 = (BasicUser) is.readObject();
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }
}


После компиляции получаем вот такой результат:


До отступа - результат работы конструктора BasicUser

После отступа - результат работы десериализации

Скажите, пожалуйста, почему в результате десириализации, программа не выводит на
экран результат работы конструктора BasicUser, хотя выводит результат работы всех родительских
классов?
    


Ответы

Ответ 1



Сериализация в java не использует конструкторы для создания объектов. Поэтому контруктор не был вызван. Но почему вызвались кострукторы родительских классов? Очевидно, т.к. они не реализовали Serializable, то механизм сериализации о них ничего не знал и поэтому инициализация происходила обычным способом - через конструктор. В сказаном легко убедиться реализовав Serializable классом Program.

Ответ 2



В дополнение к предыдущему ответу Если нужно, чтобы все конструкторы отрабатывали Немного допилил ваш код import java.io.*; class Program { Program() { System.out.println("Текст"); } } class Wild extends Program { Wild() { System.out.println("НеТекст"); } } class BasicProgrammers extends Wild { BasicProgrammers() { System.out.println("Бесполезная программа"); } } class BasicUser extends BasicProgrammers { BasicUser() { System.out.println("Использование бесполезной программы"); } } class SuperUser extends BasicUser implements Serializable { public static void main(String[] args) { SuperUser superUser = new SuperUser(); System.out.println(); try { ObjectOutputStream or = new ObjectOutputStream(new FileOutputStream("Progg.ser")); or.writeObject(superUser); or.close(); } catch (IOException ex) { ex.printStackTrace(); } try { ObjectInputStream is = new ObjectInputStream(new FileInputStream("Progg.ser")); SuperUser superUser1 = (SuperUser) is.readObject(); } catch (Exception ex) { ex.printStackTrace(); } } } Вывод: // Текст // НеТекст // Бесполезная программа // Использование бесполезной программы // // Текст // НеТекст // Бесполезная программа // Использование бесполезной программы // // Process finished with exit code 0

суббота, 8 июня 2019 г.

Теряется ссылка на один и тот же объект при сериализации-десериализации через DataContract

Пытаюсь сериализовать сложный объект через DataContract. Объект имеет список подобъектов, которые имеют в свою очередь свой список (назовем - листья дерева). К этим листьям, например, первого элемента списка основного объекта, можно добраться их других элементов списка (ссылка одна и та же). Получается довольно сложный граф, в котором много связей.
При десериализации у каждого элемента списка - свои листья, т.е. ссылки теряются, если в объекте источнике - это один и тот же лист, то после десериализации - просто копия.
Примерно так
A A / \ / \ B C ====> B C \ / | | D D D[копия]
(это очень упрощенная схема)
Пробовал для всех классов прописать DataContract(IsReference = true), так, на всякий случай - не помогло.
Есть ли более "быстрый" способ корректной десериализации, кроме как "ручное" выстраивание структуры повторяющей объект-источник?
Спасибо.


Ответ

При создании сериализатора задайте ему настройку PreserveObjectReferences = true
var settings = new DataContractSerializerSettings { PreserveObjectReferences = true }; var dcs = new DataContractSerializer(typeof(SomeType), settings);
Также можно использовать NetDataContractSerializer