Sobes.tech
Senior

Ako vytvoriť vlastný protokol serializácie?

sobes.tech AI

Odpoveď od AI

Ak chcete vytvoriť vlastný protokol serializácie v Jave, je potrebné určiť formát dát a implementovať logiku čítania/zápisu.

  1. Určte formát dát: Rozhodnite, ako budú objekty reprezentované vo formáte bajtov. Môže to byť binárny formát (kompaktnejší) alebo textový (ľahší na čítanie). Napríklad môžete použiť prefix dĺžky pred poľami.

  2. Implementujte čítanie a zápis:

    • Vytvorte triedu MySerializer (alebo podobnú), ktorá bude obsahovať metódy serialize a deserialize.
    • Metóda serialize bude prijímať objekt a OutputStream, zapisujúc bajty objektu do prúdu podľa definovaného formátu.
    • Metóda deserialize bude prijímať InputStream a bude obnovovať objekt z bajtov.
  3. Označenie tried na serializáciu: Triedy, ktoré je potrebné serializovať, by mali mať mechanizmus na interakciu so serializerom. Môže to byť:

    • Implementácia rozhrania Serializable (ale vtedy sa použije štandardný mechanizmus Javy).
    • Definovanie vlastných metód writeObject a readObject (podobne ako readObject a writeObject pre štandardnú serializáciu, ale so svojou vlastnou signatúrou).
    • Použitie anotácií na označenie polí, ktoré majú byť serializované, a ich poradia.
  4. Spracovanie odkazov na objekty: Zvážte, ako budú serializované objekty s cyklickými odkazmi alebo duplicitnými odkazmi na ten istý objekt. Môže sa použiť mechanizmus na uloženie ID objektov.

  5. Spracovanie verzií: Predvídajte, ako bude prebiehať deserializácia dát serializovaných v staršej verzii protokolu.

Príklad základnej implementácie (bez spracovania zložitých prípadov):

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

public class MySerializer {

    // Zapisuje celé číslo
    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);
    }

    // Číta celé číslo
    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;
    }

    // Zapisuje reťazec (jednoducho: dĺžka + bajty reťazca)
    public void writeString(OutputStream os, String value) throws IOException {
        byte[] bytes = value.getBytes("UTF-8");
        writeInt(os, bytes.length); // Zapisuje dĺžku
        os.write(bytes); // Zapisuje bajty reťazca
    }

    // Číta reťazec
    public String readString(InputStream is) throws IOException {
        int length = readInt(is); // Číta dĺžku
        byte[] bytes = new byte[length];
        is.read(bytes); // Číta bajty
        return new String(bytes, "UTF-8");
    }

    // Príklad serializácie jednoduchého objektu Person
    public void serialize(OutputStream os, Person person) throws IOException {
        writeString(os, person.getName());
        writeInt(os, person.getAge());
    }

    // Príklad deserializácie jednoduchého objektu Person
    public Person deserialize(InputStream is) throws IOException {
        String name = readString(is);
        int age = readInt(is);
        return new Person(name, age);
    }

    // Pomocná trieda pre príklad
    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());
    }
}

Vytvorenie vlastného protokolu si vyžaduje dôkladné plánovanie a zohľadnenie mnohých faktorov, ako sú výkon, kompaktnosť, verzovanie a spracovanie zložitých dátových štruktúr. Často sa používajú existujúce knižnice (ProtoBuf, Kryo, Avro) namiesto vytvárania protokolu od nuly.