Cereal 中的序列化和继承
Serialization and inheritance in Cereal
我希望我的程序在 JSON 文件中保存和读取配置结构。
但是,我在生成正确的 JSON 文件时遇到了问题。可能是继承问题。
JSON 输出(不正确):
{
"config": {
"confVector": [
{
"common": "a"
},
{
"common": "b"
}
]
}
}
预期(正确)JSON:
{
"config": {
"confVector": [
{
"common": "a",
"a" : 1
},
{
"common": "b",
"b" : "b"
}
]
}
}
代码:
具有公共元素的基本结构
struct Base
{
std::string common;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(common));
}
};
两种具体结构
struct A : public Base
{
int a;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(cereal::make_nvp("a", a));
}
};
struct B : public Base
{
std::string b;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(cereal::make_nvp("b", b));
}
};
struct Config
{
std::vector<Base> confVector;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(confVector));
}
};
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
主要:测试保存到 json 文件
int main()
{
std::string workPath = MAKE_STR(PLC_PROGRAM);
Config config;
A a;
a.a = 1;
a.common = "a";
B b;
b.b = "b";
b.common = "b";
config.confVector.push_back(a);
config.confVector.push_back(b);
std::ofstream outstream;
outstream.open(workPath + "/test.json");
{
cereal::JSONOutputArchive ar(outstream);
ar(cereal::make_nvp("config", config));
}
outstream.close();
}
正在对您的对象进行切片。
std::vector<Base> confVector;
这是 Base
类型对象的向量。
如果你推入派生自 Base
的对象,那么它只会复制对象的基础部分。
A a;
B b;
config.confVector.push_back(a); // a is of Type A not Base
config.confVector.push_back(b); // b is of type B not Base
所以这两个对象在放入向量时都会被切片。
您可以存储指向对象的指针:
std::vector<Base> confVector;
...
config.confVector.push_back(&a);
config.confVector.push_back(&b);
我解决了这个问题。
struct Base
{
Base() = default;
virtual ~Base() = default;
std::string common;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(common));
}
};
struct A : public Base
{
A() = default;
A(int v)
{
a = v;
}
int a;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(a);
}
};
struct B : public Base
{
B() = default;
B(std::string text)
{
b = text;
}
std::string b;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(b);
}
};
struct Config
{
std::vector<std::shared_ptr<Base>> vector;
template <class Archive>
void serialize(Archive &ar)
{
ar(vector);
}
};
CEREAL_REGISTER_TYPE(A)
CEREAL_REGISTER_TYPE_WITH_NAME(B, "ClassB")
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
int main()
{
std::string workPath = "/home/user/"
{
std::ofstream os(workPath + "polymorphism_test.json");
cereal::JSONOutputArchive oarchive(os);
std::shared_ptr<Base> ptr1 = std::make_shared<A>(123);
std::shared_ptr<Base> ptr2 = std::make_shared<B>("foobar");
Config op;
op.vector.push_back(ptr1);
op.vector.push_back(ptr2);
oarchive(op);
}
{
std::ifstream is(workPath + "polymorphism_test.json");
cereal::JSONInputArchive iarchive(is);
Config ip;
iarchive(ip);
}
return 0;
}
输出:
{
"value0": {
"value0": [
{
"polymorphic_id": 2147483649,
"polymorphic_name": "A",
"ptr_wrapper": {
"id": 2147483649,
"data": {
"Base": {
"common": ""
},
"value0": 123
}
}
},
{
"polymorphic_id": 2147483650,
"polymorphic_name": "ClassB",
"ptr_wrapper": {
"id": 2147483650,
"data": {
"Base": {
"common": ""
},
"value0": "foobar"
}
}
}
]
}
}
我希望我的程序在 JSON 文件中保存和读取配置结构。
但是,我在生成正确的 JSON 文件时遇到了问题。可能是继承问题。
JSON 输出(不正确):
{
"config": {
"confVector": [
{
"common": "a"
},
{
"common": "b"
}
]
}
}
预期(正确)JSON:
{
"config": {
"confVector": [
{
"common": "a",
"a" : 1
},
{
"common": "b",
"b" : "b"
}
]
}
}
代码:
具有公共元素的基本结构
struct Base
{
std::string common;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(common));
}
};
两种具体结构
struct A : public Base
{
int a;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(cereal::make_nvp("a", a));
}
};
struct B : public Base
{
std::string b;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(cereal::make_nvp("b", b));
}
};
struct Config
{
std::vector<Base> confVector;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(confVector));
}
};
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
主要:测试保存到 json 文件
int main()
{
std::string workPath = MAKE_STR(PLC_PROGRAM);
Config config;
A a;
a.a = 1;
a.common = "a";
B b;
b.b = "b";
b.common = "b";
config.confVector.push_back(a);
config.confVector.push_back(b);
std::ofstream outstream;
outstream.open(workPath + "/test.json");
{
cereal::JSONOutputArchive ar(outstream);
ar(cereal::make_nvp("config", config));
}
outstream.close();
}
正在对您的对象进行切片。
std::vector<Base> confVector;
这是 Base
类型对象的向量。
如果你推入派生自 Base
的对象,那么它只会复制对象的基础部分。
A a;
B b;
config.confVector.push_back(a); // a is of Type A not Base
config.confVector.push_back(b); // b is of type B not Base
所以这两个对象在放入向量时都会被切片。
您可以存储指向对象的指针:
std::vector<Base> confVector;
...
config.confVector.push_back(&a);
config.confVector.push_back(&b);
我解决了这个问题。
struct Base
{
Base() = default;
virtual ~Base() = default;
std::string common;
template <class Archive>
void serialize(Archive &ar)
{
ar(CEREAL_NVP(common));
}
};
struct A : public Base
{
A() = default;
A(int v)
{
a = v;
}
int a;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(a);
}
};
struct B : public Base
{
B() = default;
B(std::string text)
{
b = text;
}
std::string b;
template <class Archive>
void serialize(Archive &ar)
{
ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
ar(b);
}
};
struct Config
{
std::vector<std::shared_ptr<Base>> vector;
template <class Archive>
void serialize(Archive &ar)
{
ar(vector);
}
};
CEREAL_REGISTER_TYPE(A)
CEREAL_REGISTER_TYPE_WITH_NAME(B, "ClassB")
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
int main()
{
std::string workPath = "/home/user/"
{
std::ofstream os(workPath + "polymorphism_test.json");
cereal::JSONOutputArchive oarchive(os);
std::shared_ptr<Base> ptr1 = std::make_shared<A>(123);
std::shared_ptr<Base> ptr2 = std::make_shared<B>("foobar");
Config op;
op.vector.push_back(ptr1);
op.vector.push_back(ptr2);
oarchive(op);
}
{
std::ifstream is(workPath + "polymorphism_test.json");
cereal::JSONInputArchive iarchive(is);
Config ip;
iarchive(ip);
}
return 0;
}
输出:
{
"value0": {
"value0": [
{
"polymorphic_id": 2147483649,
"polymorphic_name": "A",
"ptr_wrapper": {
"id": 2147483649,
"data": {
"Base": {
"common": ""
},
"value0": 123
}
}
},
{
"polymorphic_id": 2147483650,
"polymorphic_name": "ClassB",
"ptr_wrapper": {
"id": 2147483650,
"data": {
"Base": {
"common": ""
},
"value0": "foobar"
}
}
}
]
}
}