Сериализация коллекции в Java

127
17 февраля 2022, 00:50

Можно ли проводить сериализацию не объекта класса, а коллекции?

Есть код, где пытаюсь провести сериализацию List, но значения листа не сохраняются в файл добавленный в пакет проекта, так же не проходит десериализация, на методе readObject выпадает ошибка?

public void serialize(List > String < exitData) {
  try {
    FileOutputStream a = new FileOutputStream("DataExit.json");
    ObjectOutputStream b = new ObjectOutputStream(a);
    b.writeObject(exitData);
    b.flush();
    b.close();
    a.close();
  } catch (IOException i) {
    i.printStackTrace();
  }
}
public void deSerialize() {
  try {
    FileOutputStream a = new FileOutputStream("DataExit.json");
    ObjectOutputStream b = new ObjectOutputStream(a);
    exitDeserial = (ArrayList) b.readObject(); //?????
    b.close();
    a.close();
  } catch (IOException i) {
    i.printStackTrace();
    return;
  } catch (ClassNotFoundException j) {
    System.out.println("List not found");
    j.printStackTrace();
    return;
  }
  for (String t: exitDeserial) {
    System.out.println(t);
  }
}
Answer 1

Можно сделать так:

String path = "D:\\list.obj";
List<Integer> list;        
if (!new File(path).exists()) {
    list = List.of(1, 2, 3, 4, 5);
    try (final ObjectOutputStream ObjectOutputStream = new ObjectOutputStream(new FileOutputStream(path))) {
        ObjectOutputStream.writeObject(list);
    }
} else {
    try (final FileInputStream FileOutputStream = new FileInputStream(path); 
         final ObjectInputStream ObjectInputStream = new ObjectInputStream(FileOutputStream)) {
        list = (List) ObjectInputStream.readObject();
    }
    System.out.println(list);
}

Вывод:

[1, 2, 3, 4, 5]

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

Или вообще сделать отдельно класс для этого:

public final class Serialize {
    private final String path;
    private final File file;
    private Object object;
    public Serialize(final String path) {
        this.path = path;
        this.file = new File(path);
    }
    public void serialize(final Object object) {
        try (final FileOutputStream FileOutputStream = new FileOutputStream(path);
             final ObjectOutputStream ObjectOutputStream = new ObjectOutputStream(FileOutputStream)) {
            ObjectOutputStream.writeObject(object);
        } catch (final IOException io) {
            //...логи ошибок
        }
    }
    public Object deserialize() {
        try (final FileInputStream FileOutputStream = new FileInputStream(path);
             final ObjectInputStream ObjectInputStream = new ObjectInputStream(FileOutputStream)) {
            object = ObjectInputStream.readObject();
        } catch (final IOException | ClassNotFoundException ex) {
            //...логи ошибок
        }
        return object;
    }
    public boolean is() {
        return null != this.file && this.file.exists();
    }
}

И уже использовать так:

final Serialize ser1 = new Serialize("D:\\list.obj"),
                ser2 = new Serialize("D:\\str.str");
if (!ser1.is()) {
    ser1.serialize(List.of(1, 2, 3, 4, 5));
}
List<Integer> list = (List<Integer>) ser1.deserialize();
System.out.println(list); // [1, 2, 3, 4, 5]
if (!ser2.is()) {
    ser2.serialize("String"); 
}
String string = (String) ser2.deserialize();
System.out.println(string); // String

Мможно сделать сразу динамическое приведения к нужному типу, во время вызова deserialize.

public <T> T deserialize() {
    try (final FileInputStream FileOutputStream = new FileInputStream(path);
        final ObjectInputStream ObjectInputStream = new ObjectInputStream(FileOutputStream)) {
        final Object Object = ObjectInputStream.readObject();
        final Class<?> Class = Object.getClass();
        return (T) Class.cast(Object);
    } catch (final IOException | ClassNotFoundException ex) {
        //...логи ошибок
        return null;
    }
}

И можно уже будет использовать так:

final Serialize ser1 = new Serialize("D:\\list.obj"),
                ser2 = new Serialize("D:\\str.str");
if (!ser1.is()) {
    ser1.serialize(List.of(1, 2, 3, 4, 5));
}
List<Integer> list = ser1.deserialize();
System.out.println(list); // [1, 2, 3, 4, 5]
if (!ser2.is()) {
    ser2.serialize("String"); 
}
String string = ser2.deserialize();
System.out.println(string); // String

Вывод аналогичный с вариантом выше.

Answer 2

Вы должны сериализовать объект. Да он может содержать в себе коллекции других сериализуемых объектов.

Все Ваши объекты должены реализовывать интерфейс Serializable, и содержать в себе константу serialVersionUID - уникальный идентификатор версии сериализованного класса. Чтоб объект мог быть десериализован, текущее значение в классе и в сериализованном объекте должны совпадать.

Схема такая:

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    ...
    private List<Document> documents; 
    private transient String secret; //данное поле не будет сериализовано
}

public class Document implements Serializable {
    private static final long serialVersionUID = 1L;
    ...

}

подробно можете посмотреть здесь https://javarush.ru/groups/posts/2022-serializacija-i-deserializacija-v-java

Answer 3

можно использовать обертку для сериализации/десериализации

  import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class test {
    
        public static void main(String[] args) throws IOException {
            ArrayList<SUser> objects = new ArrayList<SUser>(){{
                add(new SUser("s1", "s2"));
                add(new SUser("s1", "s2"));
            }};
            byte[] bytes = new ObjectMapper().writeValueAsBytes(objects);
            ObjectMapper objectMapper = new ObjectMapper();
            List<SUser> sUsers = objectMapper.readValue(bytes, new TypeReference<List<SUser>>() {
            });
            for (SUser sUser : sUsers) {
                System.out.println(sUser.getField1() + "   " + sUser.getField2());
            }
        }
}
////////////////////////////////////////
import java.io.Serializable;
public class SUser implements Serializable {
    private String field1;
    private String field2;
    public SUser() {
    }
    public SUser(String field1, String field2) {
        this.field1 = field1;
        this.field2 = field2;
    }
    public String getField1() {
        return field1;
    }
    public String getField2() {
        return field2;
    }
}
///////////////////////////////////////////////
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.1</version> //check for new version
        </dependency>
READ ALSO
Рандомный генератор фраз/ошибка: cannot find symbol

Рандомный генератор фраз/ошибка: cannot find symbol

Проблема возникла со словами после знака присвоения

96
Программно изменить marginBottom кнопки android

Программно изменить marginBottom кнопки android

Программно создаю кнопки, но недавно понадобилось делать отступ вниз от каждой кнопкиЯ так понял надо задать layout_marginbottom

93
Где проблема в калькуляторе?

Где проблема в калькуляторе?

Где сдесь проблема? Если например надо "-"То надо два раза вписать

125
JDK и Android Studio/Kotlin (Linux Mint 19.3)

JDK и Android Studio/Kotlin (Linux Mint 19.3)

товарищиОбъясните, кто нибудь, какой JDK нужен сейчас, для разработки под Android? В интернетах у каждого свое мнение

104