C++ में ऑब्जेक्ट सीरियलाइज़ेशन: टूल्स और लाइब्रेरी की समीक्षा
सीरियलाइज़ेशन जटिल डेटा स्ट्रक्चर (ऑब्जेक्ट, ऐरे, ग्राफ) को एक लीनियर फॉर्मेट (बाइट स्ट्रीम, JSON स्ट्रिंग, XML) में बदलने की प्रक्रिया है, जिसे फ़ाइल में सेव किया जा सकता है, नेटवर्क पर भेजा जा सकता है, या डेटाबेस में लिखा जा सकता है। उल्टी प्रक्रिया — डीसीरियलाइज़ेशन — ऑब्जेक्ट की मूल स्थिति को पुनर्स्थापित करती है। C++ में Java या Python की तरह बिल्ट-इन रिफ्लेक्शन सपोर्ट नहीं है, इसलिए सीरियलाइज़ेशन के लिए या तो मैन्युअल कोड लिखना होता है या रेडीमेड लाइब्रेरी का उपयोग करना होता है। इस लेख में हम C++ में सीरियलाइज़ेशन के सबसे लोकप्रिय और प्रभावी टूल्स पर चर्चा करेंगे।
1. Boost.Serialization
सबसे पुरानी और सबसे शक्तिशाली लाइब्रेरी। यह Boost का हिस्सा है और इसे अलग से इंस्टॉल करना होता है। यह बाइनरी, टेक्स्ट (XML) और अपने पोर्टेबल आर्काइव फॉर्मेट को सपोर्ट करती है।
- फायदे: STL, स्मार्ट पॉइंटर्स, पॉलीमॉर्फिज़्म, साइक्लिक रेफरेंस का गहरा सपोर्ट; वर्ज़निंग; विभिन्न प्लेटफॉर्म के बीच संगतता।
- नुकसान: भारी सिंटैक्स, धीमी कंपाइलेशन, बड़ा एक्ज़ीक्यूटेबल फ़ाइल साइज़।
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
#include <vector>
struct Person {
std::string name;
int age;
std::vector<std::string> tags;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & name;
ar & age;
ar & tags;
}
};
int main() {
Person p{"Alice", 30, {"developer", "cpp"}};
std::ofstream ofs("person.txt");
boost::archive::text_oarchive oa(ofs);
oa << p;
// डीसीरियलाइज़ेशन
Person restored;
std::ifstream ifs("person.txt");
boost::archive::text_iarchive ia(ifs);
ia >> restored;
return 0;
}
2. Cereal
आधुनिक, हल्की, header-only लाइब्रेरी (बिल्ड करने की ज़रूरत नहीं)। C++11 और उससे ऊपर के वर्ज़न के साथ काम करती है। JSON, XML और बाइनरी फॉर्मेट को सपोर्ट करती है। गेमिंग इंडस्ट्री और एम्बेडेड डेवलपमेंट में बहुत लोकप्रिय है।
- फायदे: न्यूनतम ओवरहेड, सहज API, स्मार्ट पॉइंटर्स, पॉलीमॉर्फिज़्म, STL कंटेनर का सपोर्ट।
- नुकसान: Boost की तुलना में कस्टमाइज़ेशन के कम विकल्प।
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/string.hpp>
#include <sstream>
struct Person {
std::string name;
int age;
template<class Archive>
void serialize(Archive & ar) {
ar(CEREAL_NVP(name), CEREAL_NVP(age));
}
};
int main() {
Person p{"Bob", 25};
std::ostringstream oss;
{
cereal::JSONOutputArchive archive(oss);
archive(CEREAL_NVP(p));
}
std::cout << oss.str() << std::endl;
// डीसीरियलाइज़ेशन
Person restored;
std::istringstream iss(oss.str());
{
cereal::JSONInputArchive archive(iss);
archive(restored);
}
return 0;
}
3. nlohmann/json (JSON for Modern C++)
C++ में JSON के साथ काम करने के लिए सबसे लोकप्रिय लाइब्रेरी। हालांकि यह मूल रूप से ऑब्जेक्ट सीरियलाइज़ेशन के लिए नहीं बनाई गई थी, लेकिन इसे कस्टम कन्वर्टर (एडेप्टर पैटर्न) के ज़रिए आसानी से अनुकूलित किया जा सकता है।
- फायदे: सरल और सुंदर सिंटैक्स, बेहतरीन डॉक्यूमेंटेशन, header-only, किसी भी टाइप के साथ इंटीग्रेशन।
- नुकसान: केवल JSON के साथ काम करती है, बाइनरी फॉर्मेट सपोर्ट नहीं करती, जटिल ऑब्जेक्ट ग्राफ के लिए मैन्युअल विवरण की आवश्यकता होती है।
#include <nlohmann/json.hpp>
#include <fstream>
using json = nlohmann::json;
struct Point {
double x, y;
};
void to_json(json& j, const Point& p) {
j = json{{"x", p.x}, {"y", p.y}};
}
void from_json(const json& j, Point& p) {
j.at("x").get_to(p.x);
j.at("y").get_to(p.y);
}
int main() {
Point pt{3.5, 7.2};
json j = pt;
std::cout << j.dump(4) << std::endl;
// डीसीरियलाइज़ेशन
Point restored = j.get<Point>();
return 0;
}
4. Protocol Buffers (protobuf)
Google द्वारा विकसित एक भाषा- और प्लेटफॉर्म-न्यूट्रल सीरियलाइज़ेशन फ्रेमवर्क। यह डेटा स्ट्रक्चर को .proto फ़ाइलों में परिभाषित करता है और फिर C++, Java, Python आदि के लिए कोड जनरेट करता है।
- फायदे: उच्च प्रदर्शन, छोटा बाइनरी आउटपुट, सख्त टाइपिंग, पिछड़ी संगतता (बैकवर्ड कम्पैटिबिलिटी)।
- नुकसान: अतिरिक्त बिल्ड स्टेप (कोड जनरेशन), सीखने की कठिनाई, डायनामिक डेटा के लिए उपयुक्त नहीं।
// person.proto
syntax = "proto3";
message Person {
string name = 1;
int32 age = 2;
repeated string tags = 3;
}
// C++ कोड
#include "person.pb.h"
#include <fstream>
int main() {
Person p;
p.set_name("Charlie");
p.set_age(28);
p.add_tags("engineer");
p.add_tags("cpp");
std::ofstream ofs("person.bin", std::ios::binary);
p.SerializeToOstream(&ofs);
// डीसीरियलाइज़ेशन
Person restored;
std::ifstream ifs("person.bin", std::ios::binary);
restored.ParseFromIstream(&ifs);
return 0;
}
5. कस्टम सीरियलाइज़ेशन (खुद का समाधान)
कभी-कभी बाहरी लाइब्रेरी का उपयोग करना संभव नहीं होता (जैसे, एम्बेडेड सिस्टम, सख्त मेमोरी सीमाएँ)। ऐसे में आप मैन्युअल सीरियलाइज़ेशन लिख सकते हैं।
- फायदे: पूर्ण नियंत्रण, कोई बाहरी निर्भरता नहीं, न्यूनतम ओवरहेड।
- नुकसान: समय लगता है, त्रुटि-प्रवण, स्केलेबल नहीं।
#include <cstring>
#include <vector>
#include <iostream>
struct Person {
std::string name;
int age;
};
std::vector<char> serialize(const Person& p) {
std::vector<char> buffer;
size_t name_len = p.name.size();
buffer.insert(buffer.end(), reinterpret_cast<const char*>(&name_len),
reinterpret_cast<const char*>(&name_len) + sizeof(name_len));
buffer.insert(buffer.end(), p.name.begin(), p.name.end());
buffer.insert(buffer.end(), reinterpret_cast<const char*>(&p.age),
reinterpret_cast<const char*>(&p.age) + sizeof(p.age));
return buffer;
}
Person deserialize(const std::vector<char>& buffer) {
Person p;
size_t offset = 0;
size_t name_len;
std::memcpy(&name_len, buffer.data() + offset, sizeof(name_len));
offset += sizeof(name_len);
p.name.assign(buffer.data() + offset, name_len);
offset += name_len;
std::memcpy(&p.age, buffer.data() + offset, sizeof(p.age));
return p;
}
int main() {
Person p{"Diana", 35};
auto data = serialize(p);
Person restored = deserialize(data);
std::cout << restored.name << ", " << restored.age << std::endl;
return 0;
}
निष्कर्ष
सीरियलाइज़ेशन लाइब्रेरी का चुनाव आपकी ज़रूरतों पर निर्भर करता है:
- Boost.Serialization — जटिल प्रोजेक्ट्स के लिए जहाँ अधिकतम सुविधाएँ चाहिए।
- Cereal — आधुनिक C++ प्रोजेक्ट्स के लिए जहाँ हल्कापन और गति महत्वपूर्ण है।
- nlohmann/json — JSON-आधारित एपीआई और कॉन्फ़िगरेशन के लिए।
- protobuf — उच्च-प्रदर्शन, क्रॉस-प्लेटफॉर्म सिस्टम के लिए।
- कस्टम समाधान — एम्बेडेड या संसाधन-सीमित वातावरण के लिए।