Sobes.tech
Senior

Kako napraviti sopstveni protokol serializacije?

sobes.tech АИ

Одговор од АИ

Да бисте креирали сопствени протокол за серијализацију у Јави, потребно је да одредите формат података и имплементирате логику читања/писања.

  1. Одредите формат података: Одлучите како ће објекти бити представљени у бајт формату. Ово може бити бинарни формат (компактнији) или текстуални (лакши за читање). На пример, можете користити префикс за дужину пре поља.

  2. Реализујте читање и писање:

    • Креирајте класу MySerializer (или сличну), која ће садржати методе serialize и deserialize.
    • Метод serialize ће примати објекат и OutputStream, записујући бајтове објекта у поток у складу са дефинисаним форматом.
    • Метод deserialize ће примати InputStream и враћати објекат из бајтова.
  3. Обележавање класа за серијализацију: Класама које треба да буду серијализоване треба обезбедити механизам за интеракцију са серијализатором. Ово може бити:

    • Реализација интерфејса Serializable (али тада ће се користити стандардни механизам Јаве).
    • Одређивање корисничких метода writeObject и readObject (слично readObject и writeObject за стандардну серијализацију, али са сопственом сигнатуром).
    • Коришћење анотација за означавање поља која треба да буду серијализована и њихов ред.
  4. Обрада референци на објекте: Размотрите како ће се серијализовати објекти са циклуским референцама или дуплираним референцама на исти објекат. Може се користити механизам за чување ID-ева објеката.

  5. Обрада верзија: Предвидите како ће се вршити десериализација података, серијализованих у старијој верзији протокола.

Пример основне реализације (без обраде сложених случајева):

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MySerializer {

    // Записује целобројно поље
    public void writeInt(OutputStream os, int value) throws IOException {
        os.write((value >>> 24) & 0xFF);
        os.write((value >>> 16) & 0xFF);
        os.write((value >>> 8) & 0xFF);
        os.write((value >>> 0) & 0xFF);
    }

    // Чита целобројно поље
    public int readInt(InputStream is) throws IOException {
        int value = 0;
        value = (is.read() << 24);
        value |= (is.read() << 16);
        value |= (is.read() << 8);
        value |= (is.read() << 0);
        return value;
    }

    // Записује низ
    public void writeString(OutputStream os, String value) throws IOException {
        byte[] bytes = value.getBytes("UTF-8");
        writeInt(os, bytes.length); // Записује дужину
        os.write(bytes); // Записује бајтове
    }

    // Чита низ
    public String readString(InputStream is) throws IOException {
        int length = readInt(is); // Чита дужину
        byte[] bytes = new byte[length];
        is.read(bytes); // Чита бајтове
        return new String(bytes, "UTF-8");
    }

    // Пример за серијализацију објекта Person
    public void serialize(OutputStream os, Person person) throws IOException {
        writeString(os, person.getName());
        writeInt(os, person.getAge());
    }

    // Пример за десериализацију објекта Person
    public Person deserialize(InputStream is) throws IOException {
        String name = readString(is);
        int age = readInt(is);
        return new Person(name, age);
    }

    // Вспомагателни клас
    public static class Person {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }
    }

    public static void main(String[] args) throws IOException {
        MySerializer serializer = new MySerializer();
        Person originalPerson = new Person("Alice", 30);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        serializer.serialize(baos, originalPerson);
        byte[] serializedData = baos.toByteArray();

        ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
        Person deserializedPerson = serializer.deserialize(bais);

        System.out.println("Original: " + originalPerson.getName() + ", " + originalPerson.getAge());
        System.out.println("Deserialized: " + deserializedPerson.getName() + ", " + deserializedPerson.getAge());
    }
}

Креирање сопственог протокола захтева пажљиво планирање и узимање у обзир многих фактора као што су перформансе, компактност, верзионирање и обрада сложених структура података. Често се користе већ постојеће библиотеке (ProtoBuf, Kryo, Avro) уместо креирања протокола од нуле.