Повышение десериализации на основе XML class_id - PullRequest
1 голос
/ 15 февраля 2020

У меня есть XML сериализованный отраженный тип, и я могу получить его сериализацию следующим образом:

template <typename Archive>
std::function<void(Archive&,unsigned)> get_serialization_for_type(std::string name);

Все эти типы имеют GUID, установленный с библиотекой расширенной сериализации, поэтому их атрибут class_id в XML соответствует действительному имени. Как я могу десериализовать эти типы? Есть ли способ получить атрибуты текущего узла, который читает архив? Также приветствуются предложения по различным подходам, но я не могу изменить формат XML.

Образец XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="17">
   ...
   <container class_id="23" tracking_level="0" version="0">
      <count>2</count>
      <typeA class_id="type_a" tracking_level="0" version="0">
         ...
      </typeA>
      <typeB class_id="type_b" tracking_level="0" version="0">
         ...
      </typeB>
   </container>
   ...
</boost_serialization>

1 Ответ

0 голосов
/ 20 февраля 2020

Это похоже на обычный Boost Serialization XML архив. Почему бы вам не прочитать его точно так же, как вы его написали?

Что я имею в виду в основном так: этот код сериализует и десериализует контейнер полиморфных c элементов с различными типами и properties.

Это делается с использованием «одного и того же» кода для сериализации и десериализации.

В принципе вы должны иметь возможность использовать этот шаблон, если XML действительно генерируется Повышенная сериализация.

Live On Coliru

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

#include <boost/serialization/vector.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/export.hpp>

#include <iostream>
#include <sstream>
#include <boost/core/demangle.hpp>

namespace MyLib {
    struct Base {
        using BaseContainer = std::vector<std::unique_ptr<Base> >;
        virtual ~Base() = default;
        int a, b, c;
    };

    struct A : Base {
        std::string d, e, f;
    };

    struct B : Base {
        float h, i, j;
    };

    template <typename Ar> void serialize(Ar& ar, Base& base, unsigned) {
        ar & BOOST_SERIALIZATION_NVP(base.a)
           & BOOST_SERIALIZATION_NVP(base.b)
           & BOOST_SERIALIZATION_NVP(base.c)
           ;
    }

    template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
        ar & boost::serialization::make_nvp("Base", boost::serialization::base_object<Base>(a))
           & BOOST_SERIALIZATION_NVP(a.d)
           & BOOST_SERIALIZATION_NVP(a.e)
           & BOOST_SERIALIZATION_NVP(a.f)
           ;
    }

    template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
        ar & boost::serialization::make_nvp("Base", boost::serialization::base_object<Base>(b))
           & BOOST_SERIALIZATION_NVP(b.h)
           & BOOST_SERIALIZATION_NVP(b.i)
           & BOOST_SERIALIZATION_NVP(b.j)
           ;
    }

    using BaseContainer = std::vector<std::unique_ptr<Base> >;
}

//BOOST_SERIALIZATION_ASSUME_ABSTRACT(MyLib::Base)
BOOST_CLASS_EXPORT(MyLib::Base)
BOOST_CLASS_EXPORT_GUID(MyLib::A, "type_A")
BOOST_CLASS_EXPORT_GUID(MyLib::B, "type_B")

int main() {
    std::stringstream xml;

    {
        MyLib::BaseContainer container;
        container.emplace_back(std::make_unique<MyLib::A>());
        container.emplace_back(std::make_unique<MyLib::B>());
        container.emplace_back(std::make_unique<MyLib::B>());
        container.emplace_back(std::make_unique<MyLib::A>());


        boost::archive::xml_oarchive oa(xml);

        oa << BOOST_SERIALIZATION_NVP(container);
    }

    //std::cout << xml.str();

    {
        boost::archive::xml_iarchive ia(xml);

        MyLib::BaseContainer container;
        ia >> BOOST_SERIALIZATION_NVP(container);

        for (auto& el : container) {
            std::cout << "Element of type " << boost::core::demangle(typeid(*el).name()) << "\n";
        }
    }
}

Отпечатки:

Element of type MyLib::A
Element of type MyLib::B
Element of type MyLib::B
Element of type MyLib::A
...