vendredi 28 août 2020

Dumping and parsing std::vector

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