Sobes.tech
Junior

Na jakie rodzaje można podzielić serializację?

sobes.tech AI

Odpowiedź od AI

Serializacja można podzielić na następujące podstawowe rodzaje, w zależności od sposobu reprezentacji danych:

  • Tekstowa: Dane są przedstawiane w czytelnym formacie, najczęściej w postaci łańcuchów znaków.

    • Zalety: Łatwość debugowania, niezależność od architektury.
    • Wady: Większy rozmiar danych, konieczność parsowania.
    • Przykłady: JSON, XML, YAML.
  • Binarną: Dane są przedstawiane w surowym, binarnym formacie.

    • Zalety: Kompaktowość, wysoka szybkość serializacji/deserializacji.
    • Wady: Trudność odczytu danych bez schematu, możliwe problemy z kompatybilnością między różnymi architekturami (np. endianness).
    • Przykłady: Protocol Buffers, Apache Thrift, Cap'n Proto, MessagePack.

Ponadto, serializację można klasyfikować według metody zastosowania:

  • Ręczną: Programista jawnie pisze kod do konwersji danych obiektu na bajty i odwrotnie.

    • Przykład:
    // Przykład ręcznej serializacji int
    int data = 12345;
    std::vector<char> buffer;
    buffer.resize(sizeof(int));
    std::memcpy(buffer.data(), &data, sizeof(int));
    
  • Automatyczną (refleksja/kodogenaracja): Używa się bibliotek lub narzędzi, które automatycznie wykonują serializację/deserializację na podstawie informacji o strukturze danych.

    • Przykład: Użycie bibliotek takich jak Boost.Serialization, cereal, RapidJSON (z własnymi adapterami), lub narzędzi do generowania kodu dla Protocol Buffers.
    // Przykład użycia boost::serialization
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/archive/binary_iarchive.hpp>
    #include <fstream>
    #include <iostream>
    
    struct MyData {
        int x;
        double y;
    
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & x;
            ar & y;
        }
    };
    
    void save(const MyData& data, const std::string& filename) {
        std::ofstream ofs(filename);
        boost::archive::binary_oarchive oa(ofs);
        oa << data;
    }
    
    void load(MyData& data, const std::string& filename) {
        std::ifstream ifs(filename);
        boost::archive::binary_iarchive ia(ifs);
        ia >> data;
    }
    

Ważne jest również rozważenie:

  • Schemat vs Bez schematu: Czy wymagana jest jawna definicja struktury danych (schemat), czy format danych jest samodzielny i opisujący się?
  • Strumieniowa vs Buforowana: Czy serializacja może odbywać się na bieżąco podczas odbioru danych, czy wymaga załadowania całej objętości danych do pamięci przed serializacją/deserializacją?