In order to parse, with https://github.com/nlohmann/json,
std::vector<std::shared_ptr<VPN>>
where VPN can be the subtypes OpenVPN
and other types like MicrosoftVPN
, CiscoVPN
, etc, I had to do the following:
void to_json(json &j, const std::shared_ptr<VPN> &p)
{
//Dont forget to set type on each subtype!!!
if (auto pp = std::dynamic_pointer_cast<OpenVPN>(p))
{
to_json(j, pp);
}
else
{
//try other subtypes then throw if none
}
}
void from_json(const json &j, std::shared_ptr<VPN> &p)
{
if (j.at("type") == "OPENVPN")
{
p = std::make_shared<OpenVPN>();
//Important: re-set the type since we recreated the instance
p->type = VPN::Type::OPENVPN;
auto pp = std::dynamic_pointer_cast<OpenVPN>(p);
from_json(j, pp);
}
else
{
//throw
}
}
then, for each subtype, I implement the to_json
and from_json
:
void to_json(json &j, const std::shared_ptr<OpenVPN> &p)
{
//Important: always set type
j = json{
{"type", p->type},
{"openvpnVersion", p->openvpnVersion},
{"profile", p->profile}};
//...
}
void from_json(const json &j, std::shared_ptr<OpenVPN> &p)
{
j.at("openvpnVersion").get_to(p->openvpnVersion);
j.at("profile").get_to(p->profile);
//...
}
As you can see, I got many problems, like if (j.at("type") == "OPENVPN")
. I have to compare with the string literal instead of the enum before I create the instance of VPN
with the subtype OpenVPN
for example. I had multiple tries after a lot of segfaults to realize what I was doing. Also I have to instantiate the pointers myself which is very easy to forget and cause segfault.
Apparently std::vector<CustomObject>
works without me having to do anything except implementing from_json
and to_json
for CustomObject
. But if CustomObject = std::shared_ptr<OtherCustomObject>
then I need to implement from_json
and to_json
for std::shared_ptr<OtherCustomObject>
.
Shouldn't or couldn't the library handle std::vector<std::shared_ptr<CustomObject>>
on its own? Do anybody have a better solution?
Aucun commentaire:
Enregistrer un commentaire