更改命名空间以自定义 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
#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>
我已进行以下更改以自定义标签名称。 下面的代码更改成功运行,我可以创建一个 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)
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
#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>