更改命名空间以自定义 boost 标签名称后的反序列化问题 xml

deserialization issue after changing namespace to customise tag names for boost xml

我已进行以下更改以自定义标签名称。 下面的代码更改成功运行,我可以创建一个 xml 具有自定义名称的文档。

namespace boost { namespace serialization {
    template <typename Ar>
        void serialize(Ar& ar,std::pair<int const , Myclass::Pgroups>& p, unsigned) {
            ar & make_nvp("assetid", p.first) & make_nvp("assetdata", p.second);
        }
} }

namespace boost { namespace serialization {
    template <typename Ar>
        void serialize(Ar& ar,std::pair<int const , values>& p, unsigned) {
            ar & make_nvp("hacc_groupid", p.first) & make_nvp("hacc_groupdata", p.second);
        }
} }

但这似乎是将 xml 反序列化到对象的问题,我收到提升错误

 template<class Archive, class Object>
   std::string serialise_to_string(const char* tag,Object & obj)
   {
     std::ostringstream os (std::ios::binary);
     Archive arch ( os );
     arch << boost::serialization::make_nvp(tag,obj);
     return os.str();
   }
   template<class Archive , class Object>
   void deserialise_to_obj( std::string const  &s1,Object &outObj)
   {
      std::stringstream is( s1, std::ios_base::binary| std::ios_base::out| std::ios_base::in);
      Archive arch (is);
      arch >> boost::serialization::make_nvp("tag",outObj);
   };

Without boost namespace customisation the serialisation and deserialisation are perfectly working , but with change in boost namespace for having customised tag names , the deserialisation has issue .

上述代码出错,即在命名空间 argvoid serialize(Ar& ar,std::pair<int const , values>& p, unsigned)

中使用 const
In file included from main.cpp:1:
In file included from /usr/local/include/boost/archive/binary_oarchive.hpp:21:
In file included from /usr/local/include/boost/archive/binary_oarchive_impl.hpp:22:
In file included from /usr/local/include/boost/archive/basic_binary_oarchive.hpp:33:
In file included from /usr/local/include/boost/archive/detail/common_oarchive.hpp:22:
In file included from /usr/local/include/boost/archive/detail/interface_oarchive.hpp:23:
In file included from /usr/local/include/boost/archive/detail/oserializer.hpp:68:
/usr/local/include/boost/archive/detail/check.hpp:162:5: error: static_assert failed "typex::value"
    BOOST_STATIC_ASSERT(typex::value);
    ^                   ~~~~~~~~~~~~
/usr/local/include/boost/static_assert.hpp:70:41: note: expanded from macro 'BOOST_STATIC_ASSERT'
#     define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
                                        ^             ~~~~~~~~~~~
/usr/local/include/boost/archive/detail/iserializer.hpp:603:13: note: in instantiation of function template specialization 'boost::archive::detail::check_const_loading<const int>' requested here
    detail::check_const_loading< T >();
            ^
/usr/local/include/boost/archive/detail/common_iarchive.hpp:66:18: note: in instantiation of function template specialization 'boost::archive::load<boost::archive::xml_iarchive, const int>' requested here
        archive::load(* this->This(), t);
                 ^
/usr/local/include/boost/archive/basic_xml_iarchive.hpp:78:39: note: in instantiation of function template specialization 'boost::archive::detail::common_iarchive<boost::archive::xml_iarchive>::load_override<const int>' requested here
        this->detail_common_iarchive::load_override(t.value());
                                      ^
/usr/local/include/boost/archive/xml_iarchive.hpp:95:38: note: in instantiation of function template specialization 'boost::archive::basic_xml_iarchive<boost::archive::xml_iarchive>::load_override<const int>' requested here
        basic_xml_iarchive<Archive>::load_override(t);
                                     ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:68:23: note: in instantiation of function template specialization 'boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load_override<const boost::serialization::nvp<const int> >' requested here
        this->This()->load_override(t);
                      ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:75:32: note: (skipping 45 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
        return *(this->This()) >> t;
                               ^
/usr/local/include/boost/archive/basic_xml_iarchive.hpp:78:39: note: in instantiation of function template specialization 'boost::archive::detail::common_iarchive<boost::archive::xml_iarchive>::load_override<Myclass>' requested here
        this->detail_common_iarchive::load_override(t.value());
                                      ^
/usr/local/include/boost/archive/xml_iarchive.hpp:95:38: note: in instantiation of function template specialization 'boost::archive::basic_xml_iarchive<boost::archive::xml_iarchive>::load_override<Myclass>' requested here
        basic_xml_iarchive<Archive>::load_override(t);
                                     ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:68:23: note: in instantiation of function template specialization 'boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load_override<const boost::serialization::nvp<Myclass> >' requested here
        this->This()->load_override(t);

If const-ness is removed from the boost namespace , deserialise_to_obj and serialise_to_string functions ,the code compiles and runs without any issue but doesn't customise the tag name

希望我的信息清楚, 我遇到了一个问题,我真的不确定是否可以使用自定义标签名称顺利地对对象进行反序列化。 请告诉我必须做什么

使用自定义标签名称进行序列化和反序列化的示例代码live at coliru

没有反序列化和自定义标签名称的示例工作代码 live at coliru

谢谢 光辉

关键在于 std::pair<>::first 对于 std::map::value_type

这是使用 const_cast 有意义的极少数情况之一:

namespace boost { namespace serialization {
    template<class Ar>
        inline void serialize(Ar & ar, std::pair<int const, values> & p, unsigned) {
            ar & make_nvp("assetid", const_cast<int&>(p.first)) & make_nvp("assetdata", p.second);
        }

    template <typename Ar>
        void serialize(Ar& ar,std::pair<int const, Myclass::Pgroups>& p, unsigned) {
            ar & make_nvp("hacc_groupid", const_cast<int&>(p.first)) & make_nvp("hacc_groupdata", p.second);
        }
} }

顺便说一下,这也是 Boost 序列化所做的:http://www.boost.org/doc/libs/1_63_0/boost/serialization/utility.hpp

完整的工作演示

Updated: Also overrides the the item node name now

Live On Coliru

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

#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>

#include <map>
#include <boost/serialization/map.hpp>
#include <boost/serialization/split_member.hpp>

using boost::serialization::make_nvp;

namespace MyDomain { // demonstrate ADL for serialize
    struct values
    {
        std::string name;
        std::string sex;
        values() : name("dummy"), sex("dummy") {};

        template<class Archive>   
            void serialize(Archive & ar, const unsigned int /*version*/) {
                ar & make_nvp("name", name);
                ar & make_nvp("sex", sex);
            }
    };

    struct Myclass {
        Myclass() { }

        template<class Archive>
            void serialize(Archive & ar, const unsigned int /*version*/)  {
                ar & make_nvp("etoto", e_group);
                ar & make_nvp("ptoto", p_group);
            }

        typedef std::map<int,values> groups;
        typedef std::map<int,groups> Pgroups;    

        groups  e_group;
        Pgroups p_group;
    };

    #define CUSTOM_MAP_SERIALIZE(Map, keyname, valuename) \
    template<class Ar> inline void serialize(Ar & ar, Map::value_type& p, unsigned) { \
            ar & make_nvp(keyname, const_cast<int&>(p.first)) & make_nvp(valuename, p.second); \
        }

    CUSTOM_MAP_SERIALIZE(Myclass::groups, "assetid", "assetdata")
    CUSTOM_MAP_SERIALIZE(Myclass::Pgroups, "hacc_groupid", "hacc_groupdata")
}

namespace boost { namespace serialization {

    #define OVERRIDE_NVP(T, name) \
       template <> inline const nvp<T> make_nvp(const char *, T &t) { return nvp<T>(name, t); } \
       template <> inline const nvp<T const> make_nvp(const char *, T const &t) { return nvp<T const>(name, t); }

    OVERRIDE_NVP(MyDomain::Myclass::groups::value_type,  "group_item")
    OVERRIDE_NVP(MyDomain::Myclass::Pgroups::value_type, "Pgroup_item")

    #undef OVERRIDE_NVP
} }

template<class Archive, class Object>
std::string serialise_to_string(Object const& assetlist)
{
    auto os = std::ostringstream(std::ios::binary);
    Archive arch { os, boost::archive::no_header };
    arch << make_nvp("Main", assetlist);
    return os.str();
}


template<class Archive , class Object>
void deserialise_to_obj(std::string const &s1,Object &outObj)
{
    std::stringstream is( s1, std::ios_base::binary| std::ios_base::out| std::ios_base::in);
    Archive arch { is, boost::archive::no_header };
    arch >> make_nvp("Main", outObj);
}

MyDomain::Myclass create_data()
{
    MyDomain::Myclass object;
    MyDomain::values val1;
    object.e_group.insert( std::make_pair(1,val1) ) ;
    object.e_group.insert( std::make_pair(2,val1) ) ;
    object.p_group.insert( std::make_pair(1,object.e_group) ) ;
    object.p_group.insert( std::make_pair(2,object.e_group) ) ;   
    return object;
}

int main() {
    {
        MyDomain::Myclass obj = create_data() ;

        std::string s2 = serialise_to_string<boost::archive::xml_oarchive>(obj);

        //Save xml to a file
        {
            std::ofstream ofs("output1.xml");
            ofs << s2 << std::endl << std::endl;
            ofs.close();
        }

    }

    std::string content;
    {
        std::ifstream ifs("output1.xml");
        content.assign(std::istreambuf_iterator<char>(ifs), {});
        ifs.close();
    }
    {
        MyDomain::Myclass outObj;
        deserialise_to_obj<boost::archive::xml_iarchive>(content,outObj);
        //Print the object 
        for(auto &i:outObj.p_group){
            std::cout<<"\n"<<i.first<<"\n";
            for(auto &j:i.second){
                std::cout<<"\t"<<j.first<<"\t"<<j.second.name<<"\t"<<j.second.sex<<"\n";
            }
        }  
    }
}

版画

1
    1   dummy   dummy
    2   dummy   dummy

2
    1   dummy   dummy
    2   dummy   dummy

与output1.xml

<Main class_id="0" tracking_level="0" version="0">
    <etoto class_id="1" tracking_level="0" version="0">
        <count>2</count>
        <item_version>0</item_version>
        <group_item class_id="2" tracking_level="0" version="0">
            <assetid>1</assetid>
            <assetdata class_id="3" tracking_level="0" version="0">
                <name>dummy</name>
                <sex>dummy</sex>
            </assetdata>
        </group_item>
        <group_item>
            <assetid>2</assetid>
            <assetdata>
                <name>dummy</name>
                <sex>dummy</sex>
            </assetdata>
        </group_item>
    </etoto>
    <ptoto class_id="4" tracking_level="0" version="0">
        <count>2</count>
        <item_version>0</item_version>
        <Pgroup_item class_id="5" tracking_level="0" version="0">
            <hacc_groupid>1</hacc_groupid>
            <hacc_groupdata>
                <count>2</count>
                <item_version>0</item_version>
                <group_item>
                    <assetid>1</assetid>
                    <assetdata>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </assetdata>
                </group_item>
                <group_item>
                    <assetid>2</assetid>
                    <assetdata>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </assetdata>
                </group_item>
            </hacc_groupdata>
        </Pgroup_item>
        <Pgroup_item>
            <hacc_groupid>2</hacc_groupid>
            <hacc_groupdata>
                <count>2</count>
                <item_version>0</item_version>
                <group_item>
                    <assetid>1</assetid>
                    <assetdata>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </assetdata>
                </group_item>
                <group_item>
                    <assetid>2</assetid>
                    <assetdata>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </assetdata>
                </group_item>
            </hacc_groupdata>
        </Pgroup_item>
    </ptoto>
</Main>