更改命名空间以自定义 Boost XML 的标记名称后的反序列化问题

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

本文关键字:问题 反序列化 命名空间 自定义 Boost XML      更新时间:2023-10-16

我进行了以下更改,为标签自定义了名称。 下面的代码更改成功运行,我可以创建一个带有自定义名称的 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反序列化为对象的问题,我收到boost错误

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);
};
如果没有 boost 命名空间自定义,序列化和反序列化

是完美的工作,但随着 boost 命名空间的变化具有自定义标签名称,反序列化有问题。

上面的代码错误,即命名空间参数中的常量void serialize(Ar& ar,std::pair<int const , values>& p, unsigned)

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);

如果从 boost 命名空间、deserialise_to_obj 和 serialise_to_string 函数中删除 const-ness,代码编译和运行没有任何问题,但不自定义标签名称

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

示例代码使用自定义标签名称进行序列化和反序列化,在 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 Serialization所做的:http://www.boost.org/doc/libs/1_63_0/boost/serialization/utility.hpp

完整工作演示

已更新:现在还覆盖item节点名称

住在科里鲁

#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

带输出1.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>